Разница между инициализацией по умолчанию и инициализацией значения в С++ 03?

Я всегда думал, что создание нового объекта всегда будет вызывать конструктор по умолчанию для объекта, и не имеет значения, был ли конструктор явным или автоматически сгенерированным компилятором. Согласно это очень рассматриваемый ответ на другой вопрос, это слегка изменилось между С++ 98 и С++ 03 и теперь работает так:

struct B { ~B(); int m; }; // non-POD, compiler generated default ctor 
new B;   // default-initializes (leaves B::m uninitialized)
new B(); // value-initializes B which zero-initializes all fields since its default ctor is compiler generated as opposed to user-defined.

Может ли кто-нибудь сказать мне:

  1. Почему был изменен стандарт, т.е. какое преимущество это дает или что теперь возможно, чего раньше не было;
  2. Что именно представляют термины «инициализация по умолчанию» и «инициализация значения»?
  3. Какова соответствующая часть стандарта?

person Mark Ransom    schedule 16.08.2011    source источник
comment
Соответствующей частью нового стандарта С++ 11 являются пункты 5,6,7 8.5 (Инициализаторы).   -  person Kerrek SB    schedule 17.08.2011
comment
Может быть, это дает людям возможность использовать ctor по умолчанию или нет. В старой версии C++ скобки обычно опускались, когда не было параметров. Таким образом, наличие квадратных скобок в новой опции меньше повлияет на устаревший код.   -  person QuentinUK    schedule 17.08.2011
comment
Я бы не назвал это изменением, а скорее коррекцией. По крайней мере, это имеет смысл в контексте, например. std::map, где значения, созданные [], являются инициализированными значениями, поэтому, например. std::map‹T,U*› все U* инициализируются в 0   -  person PlasmaHH    schedule 17.08.2011
comment
@PlasmaHH, я думаю, что у меня возникает момент лампочки - вы говорите, что до C ++ 03 типы POD не инициализировались, даже если они были созданы с помощью ()? Я уверен, что в конкретном случае std::map std::pair<A,B>() может явно вызывать конструкторы для A и B.   -  person Mark Ransom    schedule 17.08.2011
comment
@Марк Рэнсом: acceleratedcpp.com/authors/koenig/c++ std/revisions.pdf содержит неофициальный список различий между 98 и 03. В изменениях вокруг 8.5 ключевое отличие заключается в том, что для не-модулей без определенного пользователем ctor подобъекты ранее не инициализировались, потому что () было по умолчанию инициализация, которая вызвала ctor по умолчанию, который ничего не сделал. Now () - это инициализация значения, которая, когда нет определенного пользователем ctor, будет инициализировать значением все подобъекты. Поскольку пара не является POD, она всегда будет вызывать A() и B() при инициализации по умолчанию, поэтому ключ здесь, когда B() не является POD без пользователя de   -  person PlasmaHH    schedule 17.08.2011


Ответы (1)


Я не знаю, каковы причины этого изменения (или каким был стандарт раньше), но в основном инициализация по умолчанию либо вызывает пользовательский конструктор, либо ничего не делает (много ручных операций). -waving здесь: это рекурсивно применяется к каждому подобъекту, что означает, что подобъекты с конструктором по умолчанию будут инициализированы, подобъекты без определенных пользователем конструкторов останутся неинициализированными).

Это соответствует философии языка платите только за то, что вы хотите и совместимо с C во всех типах, совместимых с C. С другой стороны, вы можете запросить инициализацию значения, что эквивалентно вызову конструктора по умолчанию для объектов, у которых он или инициализируется 0 преобразованным в соответствующий тип. для остальных подобъектов.

Это описано в §8.5 Инициализаторы, и навигация по нему не является тривиальной. Определения для zero-initialize, default-initialize и value-initialize приведены в 5-м абзаце:

Инициализация нулями объекта типа T означает:

— если T — скалярный тип (3.9), объекту присваивается значение 0 (ноль), преобразованное в T;

- если T является типом класса без объединения, каждый нестатический член данных и каждый подобъект базового класса инициализируются нулями;

- если T является типом объединения, первый именованный элемент данных объекта89) инициализируется нулем;

— если T — тип массива, каждый элемент инициализируется нулями;

— если T является ссылочным типом, инициализация не выполняется.

Инициализация по умолчанию объекта типа T означает:

- если T не является типом класса POD (пункт 9), вызывается конструктор по умолчанию для T (и инициализация является некорректной, если T не имеет доступного конструктора по умолчанию);

— если T является типом массива, каждый элемент инициализируется по умолчанию;

— в противном случае объект инициализируется нулями.

Инициализация значения объекта типа T означает:

- если T является типом класса (раздел 9) с конструктором, объявленным пользователем (12.1), то вызывается конструктор по умолчанию для T (и инициализация некорректна, если у T нет доступного конструктора по умолчанию);

- если T является типом класса без объединения без объявленного пользователем конструктора, то каждый нестатический член данных и компонент базового класса T инициализируется значением;

— если T — тип массива, то каждый элемент инициализируется значением;

— в противном случае объект инициализируется нулями

Программа, которая вызывает инициализацию по умолчанию или инициализацию значения объекта ссылочного типа, имеет неправильный формат. Если T является типом cv-qualified, то cv-unqualified версия T используется для этих определений Zeroinitialization, default-initialization и value-initialization.

person David Rodríguez - dribeas    schedule 16.08.2011
comment
Ваш начальный абзац определяет поведение инициализации по умолчанию либо с использованием ctor, либо с его неинициализацией. Мой вопрос заключается в интерпретации включенной цитаты из раздела 8.5 Initializer, определяющего инициализацию по умолчанию, которая имеет последний шаг ... - в противном случае объект инициализируется нулем. Кажется, это предполагает, что если нет ctor, используйте правила нулевой инициализации, а не оставляйте его неинициализированным. - person TheChrisONeil; 05.11.2013
comment
@CBO: эта конкретная цитата из C++03, в C++11 последний элемент изменился и гласит: иначе инициализация не выполняется. Ключевым здесь является то, что написано несколькими абзацами позже. Для объекта без предоставленного инициализатора в C++03 объект остается неинициализированным (в /9), в C++11 объект инициализируется по умолчанию (/12). Не уверен, что это отвечает вашему беспокойству - person David Rodríguez - dribeas; 05.11.2013
comment
Имеет смысл и спасибо за продолжение. Я бы порекомендовал обновить ваш пост, чтобы он теперь включал содержимое C++11. - person TheChrisONeil; 05.11.2013