Порядок вызова конструктора и деструктора?

Я не могу понять порядок вызовов конструктора и деструктора? Что будет выполняться первым в этом операторе A b=f(a)? Может кто-нибудь, пожалуйста, помогите мне?

#include<iostream>
using namespace std;

class A {
    int x;

    public:
        A(int val = 0)
        :x(val) {
            cout << "A " << x << endl << flush;
        }
        A(const A& a) {
            x = a.x;
            cout << "B " << x << endl << flush;
        }
        void SetX(int x) {
            this->x = x;
        }
        ~A() {
            cout << "D " << x << endl << flush;
        }
};

A f(A a) {
    cout << " C " << endl << flush;
    a.SetX(100);
    return a;
}

int main()
{
    A a(1);
    A b=f(a);
    b.SetX(-100);
    return 0;
}

Окно вывода:

A 1
B 1
 C
B 100
D 100
D -100
D 1

Почему он печатает B 1 в строке 2 окна вывода?


person Moiz Sajid    schedule 24.04.2015    source источник
comment
Порядок — базовые классы в порядке объявленного наследования, члены в порядке объявления. Другими словами: порядок в списке инициализаторов конструктора не имеет значения (виртуальное наследование является особенным).   -  person    schedule 24.04.2015
comment
Если я правильно понимаю ваш вопрос, вы получаете B 1, потому что вы передали объект типа A в f по значению (поэтому он должен был создать копию, что привело к вызову копирующего ctor)   -  person Borgleader    schedule 24.04.2015
comment
@DieterLücking Я не понимаю, почему вы говорите здесь о наследовании, есть только один класс...   -  person Borgleader    schedule 24.04.2015
comment
@Borgleader, я полагаю, для полноты картины   -  person Marco A.    schedule 24.04.2015
comment
@DieterLücking Да? Это вполне может относиться к нескольким объектам в области, это ни в коем случае не относится конкретно к наследованию, поэтому мне любопытно, почему вы это подняли.   -  person Borgleader    schedule 24.04.2015
comment
@Moiz Если вы помечаете это как c++-faq, вы, очевидно, понимаете, что об этом часто спрашивают. Почему бы вам не закрыть его как дубликат? См. боковую панель для кандидатов: i.imgur.com/DadFylj.png   -  person sehe    schedule 24.04.2015


Ответы (1)


"Почему он печатает B 1 в строке 2?"

Поскольку конструктор копирования был вызван из этого оператора

A b=f(a);

Функция f() требует передачи A по значению, поэтому копия этого параметра создается в стеке вызова функции.


Если ваш следующий вопрос должен заключаться в том, как вы можете преодолеть это поведение и избежать вызова конструктора копирования, вы можете просто передать экземпляр A как ссылку на f():

    A& f(A& a) {
  // ^    ^
        cout << " C " << endl << flush;
        a.SetX(100);
        return a;
    }

Примечание: endl << flush; является избыточным, кстати, std::endl уже включает сброс.

person πάντα ῥεῖ    schedule 24.04.2015