Как компилятор выбирает, какой конструктор вызывать? - PullRequest
1 голос
/ 08 июля 2019

Это мой код.

Когда я удаляю строку 11, вывод будет

A(0)
B(0)
A(1)

о последней строке, "A (1)", почему второй конструктор класса A называется?

#include <iostream>

using namespace std;

class A {
public:
   A() { cout << "A(0)" << endl; }
   A(const A& a) { cout << "A(1)" << endl; }
};

class B {
public:
    B() : a() { cout << "B(0)" << endl; }
    // B(const B& b) { cout << "B(1)" << endl; }
private:
    A a;
};

int main() {
   B object1;
   B object2 = object1;
   return 0;
}
A(0)
B(0)
A(1)

Ответы [ 5 ]

7 голосов
/ 08 июля 2019

Когда

B(const B& b) { cout << "B(1)" << endl; }

закомментировано / удалено, компилятор создает для вас конструктор копирования.Этот предоставленный конструктор копирования скопирует всех членов класса, поэтому в этом случае он вытеснит конструктор копирования, который выглядит как

B(const B& copy) : a(copy.a) {}

. Именно поэтому вы видите, что конструктор копирования a вызвал.

Когда вы не комментируете / удаляете

B(const B& b) { cout << "B(1)" << endl; }

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

B(const B& b) : a() { cout << "B(1)" << endl; }

, поэтому вместо конструктора копирования вызывается конструктор по умолчанию.

1 голос
/ 08 июля 2019

Компилятор генерирует для вас конструктор копирования , который копирует элемент a. Чтобы скопировать элемент a, он по очереди вызывает его конструктор копирования, который печатает A(1).

0 голосов
/ 08 июля 2019

Проблема, с которой вы столкнулись, связана с размышлением о комментировании строки 11, означающей, что вы удалили этот конструктор.

В C ++ есть пара конструкторов, которые генерируются автоматически, если вы в конечном итоге использовали их, даже если вы не объявили их сами. Конструктор копирования, имеющий ту же сигнатуру, что и закомментированный конструктор в B, является одним из них.

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

Затем вы создаете новый объект типа B, используя оператор присваивания, который неявно вызывает созданный теперь конструктор копирования B. Это означает, что также вызывается конструктор копирования A, что является правилом в том, как конструктор копирования B является автогенерируемая. С копирующим конструктором A без комментариев он вызывается вместе с распечаткой.

0 голосов
/ 08 июля 2019

Компилятор для класса B (с закомментированным конструктором копирования) неявно определяет конструктор копирования по умолчанию, который вызывает конструкторы копирования для членов класса.

Из стандарта C ++ 20 (11.3.4.2 Конструкторы копирования / перемещения)

14 Неявно определенный конструктор копирования / перемещения для класса X без объединения выполняет пошаговое копирование / перемещение своих баз и членов ...

Неявноопределенный по умолчанию конструктор копирования класса B выглядит так:

B( const B &b ) : a( b.a )
{
}

Вот демонстрационная программа

#include <iostream>

using namespace std;

class A {
public:
   A() { cout << "A(0)" << endl; }
   A(const A& a) { cout << "A(1)" << endl; }
};

class B {
public:
    B() : a() { cout << "B(0)" << endl; }
    // An analogy of the implicitly declared copy constructor
    B(const B& b) : a( b.a ){}
private:
    A a;
};

int main() {
   B object1;
   B object2 = object1;
   return 0;
}

Вывод программы будет таким же, как если бы удалить конструктор копирования класса Bэто соответствует неявно сгенерированному конструктору копирования компилятором.

A(0)
B(0)
A(1)
0 голосов
/ 08 июля 2019

Поскольку object2 инициализируется неявным конструктором копирования из B. Неявный конструктор копирования неявно копирует все члены данных класса, следовательно, вызывается конструктор копирования A, который печатает «A (1)».

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