Если конструктор C ++ для объекта со статической продолжительностью хранения не инициализирует элемент, требуется ли это для сохранения предыдущей инициализации нуля или он оставляет элемент с неопределенным значением?
Мое чтение спецификации C ++ заключается в том, что она противоречит сама себе.
Пример:
#include <iostream>
struct Foo { Foo(); int x; } object;
Foo::Foo() { }
int main() { std::cout << object.x << std::endl; }
Конструктор Foo () явно не инициализирует член object.x, поэтому
согласно примечанию в пункте 12.6.2:
член имеет неопределенную ценность.
Но работая с деталями различных инициализаций, это, кажется,
быть неверным. Член object.x инициализируется нулями, так как он имеет static-storage-duration, и тогда я не вижу ничего, что это меняет.
Что касается конструктора, то применяется текст в 12.6.2:
объект инициализируется по умолчанию.
В п. 7 8.5 соответствующий случай инициализации по умолчанию:
… инициализация не выполняется
что я прочитал, чтобы означать, что предыдущая инициализация нуля не изменяется при инициализации по умолчанию.
Я пропускаю какой-то другой текст, который сбрасывает все члены в «неопределенное значение» в начале вызова конструктора?
Я нашел различные другие вопросы на стеке потока относительно нулевой инициализации и
инициализация по умолчанию, но я не мог видеть ничего такого
проанализировал, что происходит, когда следует инициализация по умолчанию
некоторая ранняя инициализация того же объекта.
В этом случае, вероятно, нет практического эффекта. Но в более сложном конструкторе, когда некоторые члены инициализированы, а другие нет, должен ли компилятор точно отслеживать, какие байты / биты инициализированы? Или он может просто инициализировать весь объект (например, упростив конструктор до вызова memset () )?
Отчет о дефекте 1787 привести к изменению, задокументированному в N3914 являющийся применяется к проекту стандарта для C ++ 14. Какие изменения [dcl.init] параграф 12 из:
Если для объекта не указан инициализатор, объект
по умолчанию инициализируется; если инициализация не выполняется, объект с
длительность автоматического или динамического хранения имеет неопределенное значение. [ Заметка:
Объекты со статическим или потоковым хранением инициализируются нулями,
см. 3.6.2. — конец примечания]
чтобы:
Если для объекта не указан инициализатор, объект
[…]
по умолчанию инициализируется. При хранении для объекта с автоматическим или
динамическая длительность хранения получается, объект имеет неопределенный
значение, и если для объекта не выполняется инициализация, то
объект сохраняет неопределенное значение до тех пор, пока это значение не будет заменено
(5.17 [expr.ass]). [Примечание: объекты со статическим или потоковым хранилищем
длительность инициализируется нулями, см. 3.6.2 [basic.start.init]. -конец
примечание] Если в результате оценки получено неопределенное значение,
поведение не определено, за исключением следующих случаев:
Это проясняет ситуацию неопределенного значения только для объектов автоматической или динамической длительности хранения. Поскольку это было применено в отчете о дефектах, оно, вероятно, также применимо к C ++ 11, так как отчет о дефектах возник до того, как был принят C ++ 14, но он также может применяться и в дальнейшем. Правила того, как далеко должен применяться дефект, никогда не были мне ясны.
Поскольку в комментариях было упомянуто место размещения, изменилось то же изменение. [Expr.new], сделав часть с неопределенным значением комментарием:
Если новый инициализатор опущен, объект инициализируется по умолчанию
(8.5 [dcl.init]); если. [Примечание: если инициализация не выполняется,
Объект имеет неопределенное значение. —Конечная записка]
В начале раздела говорится:
[…] Объекты, созданные новым выражением, имеют динамическое хранилище
продолжительность (3.7.4). […]
Которые кажутся достаточными, чтобы применить изменения в разделе [Dcl.init].
Это изменение было также интересно, так как до этого изменения термин неопределенное значение не было определено в стандарте C ++.
Других решений пока нет …