Рассмотрим этот кусок кода и его вывод:
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) вызовет это.
Давайте следовать вашему коду (я изменил ваш конструктор, чтобы вывести построенное это).
Во-первых, вы не хотите танировать.
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);
Ваш оператор назначения неверен:
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