Конструкция копии C++ вопрос создавать-и-присваивать

Вот является извлечение из объекта 56 из книги "Глюки C++":

Весьма распространено видеть, что простая инициализация Y возражает записанный любой из трех различных путей, как будто они были эквивалентны.

Y a( 1066 ); 
Y b = Y(1066);
Y c = 1066;

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

Инициализации b и c более сложны. На самом деле они слишком сложны. Это оба инициализации копии. В случае инициализации b мы запрашиваем создание анонимного временного файла типа Y, инициализированного со значением 1066. Мы затем используем этот анонимный временный файл в качестве параметра для конструктора копии для класса Y для инициализации b. Наконец, мы называем деструктор для анонимного временного файла.

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

Кто-либо знает, изменился ли стандарт языка, или это - просто функция оптимизации компилятора? Я использовал Visual Studio 2008.

Пример кода:

#include <iostream>

class Widget
{
    std::string name;
public:
    // Constructor
    Widget(std::string n) { name=n; std::cout << "Constructing Widget " << this->name << std::endl; }
    // Copy constructor
    Widget (const Widget& rhs) { std::cout << "Copy constructing Widget from " << rhs.name << std::endl; }
    // Assignment operator
    Widget& operator=(const Widget& rhs) { std::cout << "Assigning Widget from " << rhs.name << " to " << this->name << std::endl; return *this; }
};

int main(void)
{
    // construct
    Widget a("a");
    // copy construct
    Widget b(a);
    // construct and assign
    Widget c("c"); 
    c = a;
    // copy construct!
    Widget d = a;
    // construct!
    Widget e = "e";
    // construct and assign
    Widget f = Widget("f");

    return 0;
}

Вывод:

Constructing Widget a

Copy constructing Widget from a

Constructing Widget c
Assigning Widget from a to c

Copy constructing Widget from a

Constructing Widget e

Constructing Widget f
Copy constructing Widget from f

Я был больше всего удивлен результатами построения d и e. Чтобы быть точным, я ожидал, что пустой объект будет создан, и затем объект, который будет создан и присвоен пустому объекту. На практике объекты были созданы конструктором копии.

7
задан Andy 17 March 2010 в 14:06
поделиться

2 ответа

Синтаксис

X a = b;

где a и b имеют тип X, всегда означал копирование конструкции. Какие бы варианты, такие как:

X a = X();

не использовались, никакого присваивания не происходит, и никогда не происходило. Конструирование и присваивание было бы чем-то вроде:

X a;
a = X();
16
ответ дан 6 December 2019 в 07:25
поделиться

Компилятору разрешено оптимизировать случаи b и c, чтобы они были такими же, как a. Кроме того, вызовы операторов копирования и присваивания могут быть полностью исключены компилятором в любом случае, поэтому то, что вы видите, не обязательно будет одинаковым для разных компиляторов или даже настроек компилятора.

6
ответ дан 6 December 2019 в 07:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: