Подтвердить что ты не робот

Должен ли конструктор когда-либо вызываться при назначении?

Вывод кода, приведенного ниже в VS2015, является "конструктором".

Должен ли он не скомпилироваться из-за отсутствующего оператора присваивания?

struct A { };

struct B {
    B(){}
    B(const A& a) {
        cout << "constructor" << endl;
    }

    //B& operator=(const A& a) {
    //  cout << "assignment operator" << endl;
    //  return *this;
    //}
};

int main() {
    A a;
    B b;
    b = a;

    return 0;
}
4b9b3361

Ответ 1

Да, когда происходит конверсия, как в вашем тестовом файле.

Вы действительно называете

b = B(a);

Поскольку оператор присваивания B B& operator=(B const&) неявно объявлен, он обнаруживается при разрешении перегрузки. Поскольку ваше задание - это только одно преобразование от совпадения (и что именно количество преобразований, которое разрешено), оно преобразует a в B, а затем назначает новый временный B на B.

Ответ 2

Рассмотрим аналогичный пример.

double a;
int b=5;

a=b;

Единственное, что вы можете назначить double, - это еще один double. Однако int можно преобразовать в double.

Аналогично здесь A можно преобразовать в B, потому что существует такой конструктор. И что происходит.

Ответ 3

Ваш код имеет неявное преобразование от A до B, b = a скомпилирован как b = B(a);. Если вы хотите, чтобы это было обнаружено как ошибка, вы можете использовать спецификатор explicit:

struct B {
    B(){}
    explicit B(const A& a) {
        std::cout << "constructor" << std::endl;
    }
};

Затем вы должны получить сообщение об ошибке, например сгенерированные ideone.com:

prog.cpp: In function 'int main()':
prog.cpp:20:7: error: no match for 'operator=' (operand types are 'B' and 'A')
     b = a;
       ^
prog.cpp:5:8: note: candidate: B& B::operator=(const B&)
 struct B {
        ^
prog.cpp:5:8: note:   no known conversion for argument 1 from 'A' to 'const B&'
prog.cpp:5:8: note: candidate: B& B::operator=(B&&)
prog.cpp:5:8: note:   no known conversion for argument 1 from 'A' to 'B&&'

После этого конструктор никогда не будет вызван неявным образом, и если вы хотите его называть, вы должны явно его написать: b = B(a);