拷贝构造函数如何执行?
How does copy constructor execute?
我正在尝试详细了解复制构造函数。在这样做的同时,我做了以下示例,
#include<iostream>
class Test
{
private:
int a;
public:
/*
Test(const Test &t) // User defined copy constructor
{
a = t.a;
} */
Test()
{
a = 120;
}
int display()
{
return a ;
}
void set(int var)
{
a = var;
}
};
int main()
{
Test t1;
std::cout << "t1.a " << t1.display() << std::endl;
Test t2 = t1; //Default copy constructor is called
std::cout << "T2.a " << t2.display() << std::endl;
t2.set(99); //Changing the value
std::cout << "t1.a " << t1.display() << std::endl;
std::cout << "T2.a " << t2.display() << std::endl;
return 0;
}
我在网上看到默认复制构造函数 "shallow copy" 所以这意味着如果 obj1 = obj2,即使在赋值之后我在 obj1 或 obj2 中做了什么改变
需要反映在两个对象上,因为它们指向相同的位置。
但是在这个例子中,当我改变一个对象的值时,它并没有反映在另一个对象中。使用用户定义的复制构造函数时获得相同的结果。
谁能澄清一下这个话题,浅拷贝是否正在发生!
谢谢!
考虑浅拷贝到单纯的赋值。所以,
Test t2 = t1;
表示
t2.a = t1.a
由于a
是一个int
,如果您从t1
修改a
,它不会反映在t2
中。
所以对于int
浅拷贝确实是深拷贝。
考虑案例 a
的类型 int*
。现在 t2.a
和 t1.a
都指向相同的内存位置。因此,如果您修改内存位置 t1.a
处的值,相同的内容将通过 t2.a
反映出来,因为它们实际上指向相同的位置。
浅拷贝不是什么特殊的东西,你需要记住它作为规则。相反,它只是由于使用引用或指针而发生的事情。考虑这个例子:
struct foo {
int* x;
};
int a = 4;
foo f{&a};
此处 x
指向 a
,如果您复制 f
,新实例 x
将指向相同的 a
。那是一个浅拷贝。深拷贝不仅要尊重 x
,还要尊重 x
指向的内容,它们是 foo
的组成部分,也需要复制。一般来说,编译器无法决定你想要什么。 x
只是一个参考,还是 x
所指的也是 foo
的一部分?因此你得到的是显而易见的:只复制成员而不是他们可能引用的内容。
现在,如果您复制 foo
,然后修改 x
指向的值,那么这将修改相同的 a
。做了一个浅拷贝。根据我的经验,术语深拷贝和浅拷贝与其说是清晰,不如说是在增加混乱。您免费获得的是所有成员都被复制(无论是浅拷贝还是深拷贝)。只有当你需要更多(也复制指针)时,你才需要担心浅拷贝和深拷贝。
TL;DR:您的示例中没有 deep/shallow 副本。对于价值观,这种区分没有意义。用一个int*
看看效果。
class 的隐式定义的复制构造函数简单地复制每个成员 [class.copy.ctor]/14。复制成员基本上意味着新对象(被复制到的那个)的每个成员都是从被复制对象的相应成员初始化的,就像你写的一样
T member(original.member);
其中 T
是成员的类型,original
是被复制的对象。如果 member
是 class 类型,这实际上归结为调用 T
的复制构造函数。但是,您的成员是普通 int
,不是 class 类型。没有拷贝构造函数可以调用(int
没有拷贝构造函数);新对象中的 int
只是简单地从原始对象的 int
初始化,归结为将原始 int
的值复制到新的 int
...
你的编译器不区分深拷贝和浅拷贝,它甚至不知道 "deep copy" 或 "shallow copy" 是什么意思。在语言级别上,C++ 中没有深拷贝或浅拷贝之类的东西。这些只是程序员常用的简单术语,用于谈论复制 逻辑上(但不是物理上)包含其他对象的对象的不同方法......
I read online that default copy constructor does "shallow copy"
这不是拷贝构造函数的正确思路。默认的复制构造函数只是复制类型中的任何成员,就好像在成员上依次应用复制构造函数一样。
参考资料:
If the implicitly-declared copy constructor is not deleted, it is
defined (that is, a function body is generated and compiled) by the
compiler if odr-used. For union types, the implicitly-defined copy
constructor copies the object representation (as by std::memmove). For
non-union class types (class and struct), the constructor performs
full member-wise copy of the object's bases and non-static members, in
their initialization order, using direct initialization.
所以它实际上更像是深拷贝而不是浅拷贝。
我正在尝试详细了解复制构造函数。在这样做的同时,我做了以下示例,
#include<iostream>
class Test
{
private:
int a;
public:
/*
Test(const Test &t) // User defined copy constructor
{
a = t.a;
} */
Test()
{
a = 120;
}
int display()
{
return a ;
}
void set(int var)
{
a = var;
}
};
int main()
{
Test t1;
std::cout << "t1.a " << t1.display() << std::endl;
Test t2 = t1; //Default copy constructor is called
std::cout << "T2.a " << t2.display() << std::endl;
t2.set(99); //Changing the value
std::cout << "t1.a " << t1.display() << std::endl;
std::cout << "T2.a " << t2.display() << std::endl;
return 0;
}
我在网上看到默认复制构造函数 "shallow copy" 所以这意味着如果 obj1 = obj2,即使在赋值之后我在 obj1 或 obj2 中做了什么改变 需要反映在两个对象上,因为它们指向相同的位置。 但是在这个例子中,当我改变一个对象的值时,它并没有反映在另一个对象中。使用用户定义的复制构造函数时获得相同的结果。
谁能澄清一下这个话题,浅拷贝是否正在发生!
谢谢!
考虑浅拷贝到单纯的赋值。所以,
Test t2 = t1;
表示
t2.a = t1.a
由于a
是一个int
,如果您从t1
修改a
,它不会反映在t2
中。
所以对于int
浅拷贝确实是深拷贝。
考虑案例 a
的类型 int*
。现在 t2.a
和 t1.a
都指向相同的内存位置。因此,如果您修改内存位置 t1.a
处的值,相同的内容将通过 t2.a
反映出来,因为它们实际上指向相同的位置。
浅拷贝不是什么特殊的东西,你需要记住它作为规则。相反,它只是由于使用引用或指针而发生的事情。考虑这个例子:
struct foo {
int* x;
};
int a = 4;
foo f{&a};
此处 x
指向 a
,如果您复制 f
,新实例 x
将指向相同的 a
。那是一个浅拷贝。深拷贝不仅要尊重 x
,还要尊重 x
指向的内容,它们是 foo
的组成部分,也需要复制。一般来说,编译器无法决定你想要什么。 x
只是一个参考,还是 x
所指的也是 foo
的一部分?因此你得到的是显而易见的:只复制成员而不是他们可能引用的内容。
现在,如果您复制 foo
,然后修改 x
指向的值,那么这将修改相同的 a
。做了一个浅拷贝。根据我的经验,术语深拷贝和浅拷贝与其说是清晰,不如说是在增加混乱。您免费获得的是所有成员都被复制(无论是浅拷贝还是深拷贝)。只有当你需要更多(也复制指针)时,你才需要担心浅拷贝和深拷贝。
TL;DR:您的示例中没有 deep/shallow 副本。对于价值观,这种区分没有意义。用一个int*
看看效果。
class 的隐式定义的复制构造函数简单地复制每个成员 [class.copy.ctor]/14。复制成员基本上意味着新对象(被复制到的那个)的每个成员都是从被复制对象的相应成员初始化的,就像你写的一样
T member(original.member);
其中 T
是成员的类型,original
是被复制的对象。如果 member
是 class 类型,这实际上归结为调用 T
的复制构造函数。但是,您的成员是普通 int
,不是 class 类型。没有拷贝构造函数可以调用(int
没有拷贝构造函数);新对象中的 int
只是简单地从原始对象的 int
初始化,归结为将原始 int
的值复制到新的 int
...
你的编译器不区分深拷贝和浅拷贝,它甚至不知道 "deep copy" 或 "shallow copy" 是什么意思。在语言级别上,C++ 中没有深拷贝或浅拷贝之类的东西。这些只是程序员常用的简单术语,用于谈论复制 逻辑上(但不是物理上)包含其他对象的对象的不同方法......
I read online that default copy constructor does "shallow copy"
这不是拷贝构造函数的正确思路。默认的复制构造函数只是复制类型中的任何成员,就好像在成员上依次应用复制构造函数一样。
参考资料:
If the implicitly-declared copy constructor is not deleted, it is defined (that is, a function body is generated and compiled) by the compiler if odr-used. For union types, the implicitly-defined copy constructor copies the object representation (as by std::memmove). For non-union class types (class and struct), the constructor performs full member-wise copy of the object's bases and non-static members, in their initialization order, using direct initialization.
所以它实际上更像是深拷贝而不是浅拷贝。