Когда я возвращаю по значению из оператора присваивания, во-первых, каков механизм и основание для вызова конструктора копирования?

Рассмотрим этот кусок кода и его вывод:

class test {
int a, b;

public:
test (int a, int b) : a(a), b(b) { cout << "Const" << endl;}

test (const test & t) {
cout << "Copy constructor" << endl;
cout << "Being copied to = " << this << " from " <<  &t << endl;
if (&t == this) {
cout << "returning" << endl;
return;
}
this->a = t.a;
this->b = 6;//t.b;
}

test operator=(const test & in) {
cout << "Assignment operator" << endl;
this->a = in.a;
this->b = in.b;
cout << "Being written to = " << this << " from  "<< &in << endl;
return *this;
}

test get () {
test l = test (3, 3);
cout << "Local return " << &l << endl;
return l;
}

void display () {
cout << a << " " << b << endl;
}
};

int main () {
int i = 5, &ref = i;
test t(1,1), u(2,2);

u = t.get();
cout << "u address" << &u <<endl;
//cout << "u ka = " << &u << endl;
u.display();
}

Выход:

Const
Const
Const
Local return 0x7fff680e5ab0
Assignment operator
Being written to = 0x7fff680e5a90 from  0x7fff680e5ab0
Copy constructor
Being copied to = 0x7fff680e5a80 from 0x7fff680e5a90
u address0x7fff680e5a90
3 3

Я знаю, что способ возврата из задания — по ссылке, но я пытался понять, как это работает, так как я новичок в C ++.
Какой адрес 0x7fff680e5a80? Откуда это? Какой объект вызывает конструктор копирования здесь? Я ожидал бы, что u (адрес 0x7fff680e5a90) вызовет это.

1

Решение

Давайте следовать вашему коду (я изменил ваш конструктор, чтобы вывести построенное это).

Во-первых, вы не хотите танировать.

Const at 0x7fffffffdeb0
Const at 0x7fffffffdea0

Затем вы вызываете t.get, который инициализирует l.

Const at 0x7fffffffdec0

Затем вы возвращаете л.

Local return 0x7fffffffdec0

Конструктор копирования, который обычно происходит в этот момент, исключается.

Assignment operator from l to u
Being written to = 0x7fffffffdea0 from  0x7fffffffdec0

Затем вы возвращаете присваивание по значению (вы должны вернуть его по ссылке), поэтому вы копируете из u в выходное значение, которое не сохраняется (0x7fffffffde90 из u)

Copy constructor
Being copied to = 0x7fffffffde90 from 0x7fffffffdea0

И тогда вы печатаете.

u address0x7fffffffdea0

Внутри Т.

Чтобы избавиться от запутанной (и ненужной копии), вам следует возвращаться по ссылке, когда вы выполняете любой оператор присваивания:

test& operator=(const test & in);
2

Другие решения

Ваш оператор назначения неверен:

    test operator=(const test & in) {

Вы должны вернуться по ссылке:

    test &operator=(const test & in) {

Объект на 0x7fff680e5a80 является prvalue временным объектом типа test это возвращается от вашего (неправильного) оператора присваивания и немедленно удаляется:

test operator=(const test & in) {
cout << "Assignment operator" << endl;
this->a = in.a;
this->b = in.b;
cout << "Being written to = " << this << " from  "<< &in << endl;
return *this;
}   //     ^-- copy constructor is called here

Вы можете проверить это, взяв rvalue ссылку на возвращаемое значение оператора присваивания:

auto &&temp = (u = t.get());
std::cout << "Address of temp: " << &temp << std::endl;  // prints 0x7fffffffde90
1

По вопросам рекламы [email protected]