2013-04-17 16 views
3

Я начинаю программирование на C++, и у меня есть простой вопрос относительно конструктора классов C++. Сколько раз конструктор вызывается для следующего кода?Сколько раз вызывается конструктор?

std::string s = std::string("hello world"); 

Я думаю, это два, не так ли? Первая из них - строка (const char * s), вторая - строка (const string & s). Пожалуйста, поправьте меня, если я ошибаюсь.

Следующий вопрос заключается в том, что, если я скомпилирую код в режиме выпуска, будет ли его компилятор автоматически оптимизировать? например обрабатывать его как std::string s("hello world"); Делает ли другой компилятор по-другому?

+0

проверить конструктор move в C++ 11. –

+0

Каково поведение C++ 03? –

ответ

4

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

std::string s(std::string("hello world")); 

Без оптимизаций будут вызываться два конструктора, как вы описали. В C++ 11 конструктор перемещения будет предпочтительным для второго этапа (определяется как string(string&&)), потому что std::string("hello world") является выражением rvalue. Однако стандарт явно позволяет элизия копий/ходов в некоторых случаях, в том числе это:

когда объект временного класса, который не был связан с ссылкой (12.2) будут скопированы/перемещены в класс объект с тем же сорте-неквалифицированным типа, операция копирования/перемещения может быть опущен, построив временный объект непосредственно в мишень опущенным копирования/перемещения

Таким образом, компилятор может, если он выбирает, оптимизировать прочь копия. Обратите внимание, что компилятор может это сделать, даже если конструктор копирования имеет некоторые странные побочные эффекты. То есть, вполне возможно, что вполне определенная и действительная программа на C++ имеет несколько возможных путей выполнения. Как правило, вы хотите этого избежать.

+0

Чтобы быть педантичным, это не «точно то же самое», так как неявный конструктор должен быть доступен для инициализации копирования, и в принципе копирование-инициализация позволяет компилятору вызывать два конструктора (на практике ни один из разумных компиляторов никогда не будет). –

+0

@KerrekSB Плохая формулировка с моей стороны. Изменено «точно» до «очень много». Однако обе формы могли бы называть два конструктора, нет? –

+0

Прямая инициализация может * не * вызвать два конструктора, я уверен ... На самом деле, очень уверен, поскольку вы можете удалить конструкторы копирования и по-прежнему выполнять прямую инициализацию. –

3

Ваш код имеет право на копирование, поэтому большинство здравомыслящих компиляторов всегда будут рассматривать это как std::string s("hello world");, если явно не указано, что этого не делать.

Смежные вопросы