Почему ни конструктор, ни оператор присваивания не выполняются при объявлении объекта? - PullRequest
3 голосов
/ 27 декабря 2010

Тестовая программа

#include <iostream>
using namespace std;

class A
   {public:
       A (): I(0) {cout << "default construcot" << endl; };
       explicit A (int i): I(i) {cout << "another construcot" << endl; };
       A (const A& a): I(a.I) {cout << "copy constructor" << endl; }
       A& operator = (const A& a)
          {cout << "assignment operator" << endl; 
           if (this == &a) return *this; 
           I = a.I;
           return *this; 
          }
       void show () {cout << I << endl; };
    private:
       int I;
   };

int main ()
   {A a = A(1);
    A b;
    b = A(2);
    a.show();
    b.show();
    return 0;
   }

выход

another construcot
default construcot
another construcot
assignment operator
1
2

показывает, что объект «a» в отличие от «b» был построен из A (1) «напрямую» без выполнения оператора присваивания. Но конструктор копирования тоже не был выполнен. Зачем? Есть ли способ форсировать выполнение оператора присваивания в этом случае? Я бы ожидал такого поведения, если бы написал

A a (1);

но я хочу

A a = A(1);

, которые должны отличаться от первого случая. Или нет?

(На самом деле проблема возникает, когда у меня есть класс B, производный от A, и я хочу, чтобы оператор присваивания A обрабатывал объявление, например, A a = B (...).)

Ответы [ 5 ]

6 голосов
/ 27 декабря 2010

Это

A a = A(1);

не эквивалентно этому:

A a;
a = A(1);

Во втором случае = является оператором, в первом случае = не является оператором. В первом утверждении это синтаксис инициализации. Компилятор может вызвать конструктор копирования , но он может оптимизировать его, так как это одно из мест, где это разрешено языком (RVO, выброс исключения и т. Д.).

3 голосов
/ 27 декабря 2010

Почему

Стандарт позволяет компилятору оптимизировать конструкцию копии.Не это НЕ присваивание, поскольку оно является частью объявления (поэтому, если оптимизация не была выполнена, это привело бы к временному объекту, а затем к копированию конструкции временного объекта в a).

Есть ли способ форсировать выполнение оператора присваивания в этом случае.

Это будет зависеть от вашего компилятора.Но я не знаю ни одного, который позволил бы вам форсировать это (но я никогда не пытался отключить его).Попробуйте отключить все оптимизации, которые выполняет ваш компилятор.

Я бы ожидал такого поведения, если бы написал: A a (1);

Стандарт прямо заявляет, что вашверсия может быть оптимизирована для этого.

У меня есть класс B, производный от A, и я хочу, чтобы оператор присваивания A обрабатывал объявления вроде A a = B (...).)

Если вы сделаете это, вы нарежете B и просто назначите часть A объекта B.
Хотите использовать ссылку?

A const& a = B();
1 голос
/ 28 декабря 2010

Надеюсь A a(1); и A a = 1; - это одно и то же, это гарантировано стандартом.

1 голос
/ 27 декабря 2010

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

1 голос
/ 27 декабря 2010

Почему?Потому что компилятор делает это совершенно бесплатно, и большинство делает.

Можете ли вы форсировать это?Нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...