почему два способа инициализации переменных

Почему С++ предоставляет два способа инициализации переменной?

Первый способ — C-type initialization, где мы присваиваем значение переменной в том месте, где мы ее определяем.

int a = 0;

Другой способ, constructor initialization, заключается в заключении начального значения в круглые скобки ().

int a(0);

Мой вопрос в том, по какой причине создатели C++ были вынуждены ввести новый способ инициализации переменных. Хотя инициализация в стиле C делала свое дело.


person HadeS    schedule 25.09.2015    source источник
comment
Вы знакомы с многопараметрическими конструкторами, верно?   -  person Angew is no longer proud of SO    schedule 25.09.2015
comment
вы забыли третий ({ }) способ :)   -  person Ziezi    schedule 25.09.2015
comment
вы можете начать с проверки любых объяснений в текущем (бесплатном) рабочем проекте стандарта C++: isocpp.org /стандартный/стандартный   -  person Ziezi    schedule 25.09.2015
comment
И четвертый способ: auto i = 0;   -  person TartanLlama    schedule 25.09.2015
comment
@TartanLlama Это просто вывод типа, нет никакой разницы в семантике или синтаксисе инициализации.   -  person Asad Saeeduddin    schedule 25.09.2015
comment
@ Как хорошо, синтаксис другой, и семантика другая, если вы соедините его с инициализацией в фигурных скобках.   -  person TartanLlama    schedule 25.09.2015
comment
@TartanLlama Я застрял в C++98... мало знаком с C++11/C++14   -  person HadeS    schedule 25.09.2015
comment
@HadeS это недавнее статья Скотта Мейерса на эту тему может вас заинтересовать.   -  person TartanLlama    schedule 25.09.2015
comment
Их заставили или они выбрали?   -  person ChiefTwoPencils    schedule 25.09.2015
comment
@Angew Да, я знаю о конструкторе с несколькими параметрами ... Пожалуйста, уточните свой комментарий ...   -  person HadeS    schedule 25.09.2015
comment
Итак, как бы вы использовали конструктор с несколькими параметрами без синтаксиса прямой инициализации (( ))? И без (даже условно) создания временного объекта?   -  person Angew is no longer proud of SO    schedule 25.09.2015
comment
@Angew, почему это доступно для встроенных типов... Точка действительна для пользовательских типов.... или для встроенных типов нет никакой разницы...   -  person HadeS    schedule 25.09.2015


Ответы (3)


int a = 0; существует для устаревших (и потому, что это кажется естественным, особенно для встроенных типов), а int a(0) существует для ясности и согласованности — бывают ситуации, когда вам может понадобиться более сложный конструктор копирования, который принимает несколько аргументов или аргументов других типов (преобразование конструкторы).

Если это возможно (т. е. если доступен соответствующий конструктор), компилятор будет рассматривать как int a = 0;, так и int a(0) как вызов конструктора копирования. Точное поведение объясняется здесь.

Я думаю, это связано с тем, что конструкторы со списками инициализаторов обычно работают быстрее, что, как я думаю, связано с тем фактом, что значение может быть помещено во вновь выделенную переменную память за меньшее количество операций доступа к памяти. Здесь находится FAQ CPP по этой теме (отличный веб-сайт для таких вопросов, Кстати).

person stett    schedule 25.09.2015
comment
Вы должны пояснить, что ваше ведущее утверждение является заблуждением, иначе вы создадите впечатление, что оно верно. - person juanchopanza; 25.09.2015
comment
@juanchopanza - да, хорошая мысль. Я обновил свой ответ, чтобы сделать его более прямым. - person stett; 25.09.2015
comment
Я также не думаю, что компилятор заменит int a = 0; на int a(0); правильно. Компилятор не обязан этого делать, и стандарт не говорит, что должен. - person juanchopanza; 25.09.2015
comment
Инициализация копированием выполняется в следующих ситуациях: 1) когда именованная переменная (автоматическая, статическая или локальная для потока) не ссылочного типа T объявлена ​​с инициализатором, состоящим из знака равенства, за которым следует выражение. - en.cppreference.com/w/cpp/language/copy_initialization - person stett; 25.09.2015
comment
Это не означает, что компилятор заменяет одно другим. - person juanchopanza; 25.09.2015
comment
Хм, да, возможно, вы правы - моя формулировка неверна... Я не знаю, что она заменяет, но трактует одно как другое. - person stett; 25.09.2015
comment
Я бы сказал, что они функционально эквивалентны, если задействованные типы имеют определенные свойства, а не то, что они заменены или рассматриваются как один другой. - person TartanLlama; 25.09.2015
comment
Я думаю, вы могли бы сказать, что при определенных условиях (которые относятся к примеру OP) они эквивалентны. - person juanchopanza; 25.09.2015

В основном неявный является предпочтительным способом:

int nValue = 5; // explicit initialization

int nValue(5); // implicit initialization

Вот некоторые чтения:

http://www.learncpp.com/cpp-tutorial/21-basic-addressing-and-variable-declaration/

Явное назначение против неявного назначения

person Wald    schedule 25.09.2015
comment
Термины explicit initialization и implicit initialization кажутся мне перепутанными и неточными. Официальными терминами являются инициализация копированием и прямая инициализация. - person TartanLlama; 25.09.2015

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

person rockworm    schedule 25.09.2015
comment
Это неправда, инициализация копирования никогда не вызывает конструктор по умолчанию. - person TartanLlama; 25.09.2015
comment
Проверьте это: en.cppreference.com/w/cpp/language/copy_initialization - person stett; 25.09.2015
comment
Хм... как избежать вызова конструктора по умолчанию? - person rockworm; 25.09.2015
comment
Это по-прежнему инициализация не присваивания. Когда вы говорите T a = b;, а b имеет тип T, это то же самое, что и T a(b); (по модулю явных ctors). Когда b не относится к типу T, это то же самое, что и T a(T(b));. Нет присваивания и нет конструкции по умолчанию. - person Angew is no longer proud of SO; 25.09.2015