复制构造函数如何执行?
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;
}
我在网上读到默认复制构造函数做"浅拷贝"所以这意味着如果 obj1 = obj2,即使在赋值之后我在 obj1 或 obj2 中所做的任何更改 需要反映在两个对象上,因为它们指向同一位置。 但是在这个例子中,当我更改一个对象的值时,它不会反映在另一个对象中。使用用户定义的复制构造函数时,将获得相同的结果。
有人可以澄清这个话题吗,无论是否正在发生浅层复制!
谢谢!
浅拷贝不是你需要记住的特殊东西。相反,它只是由于使用引用或指针而发生的事情。康赛德这个例子:
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:在你的例子中没有深/浅的副本。对于值,这种区别是没有意义的。使用int*
查看效果。
我在网上读到默认复制构造函数做"浅拷贝">
这不是复制构造函数的正确思维方式。默认复制构造函数只是复制类型中的任何成员,就像依次对成员应用复制构造函数一样。
参考资料:
如果未删除隐式声明的复制构造函数,则它是 定义(即,生成和编译函数体)由 编译器(如果使用 ODR)。对于联合类型,隐式定义的副本 构造函数复制对象表示形式(如 std::memmove)。为 非联合类类型(类和结构),构造函数执行 对象基和非静态成员的完整成员副本,在 它们的初始化顺序,使用直接初始化。
所以它实际上更像是一个深拷贝,而不是一个浅拷贝。
考虑将浅拷贝仅仅赋值。所以
Test t2 = t1;
方法
t2.a = t1.a
由于a
是int
,如果修改a
,从t1
,就不会反映在t2
中。 所以对于int
浅拷贝确实是深拷贝。
考虑a
属于int*
型的情况。现在t2.a
和t1.a
都指向相同的内存位置。因此,如果您修改内存位置的值t1.a
,同样会通过t2.a
反映出来,因为它们实际上指向同一位置。
类的隐式定义复制构造函数只是复制每个成员 [class.copy.ctor]/14。复制成员基本上意味着新对象(被复制到的对象)的每个成员都是从被复制对象的相应成员初始化的,就像你写的那样
T member(original.member);
其中T
是成员的类型,original
是要复制的对象。如果member
是类类型,这实际上归结为调用T
的复制构造函数。但是,您的成员是普通int
,这不是类类型。没有要调用的复制构造函数(int
没有复制构造函数);新对象中的int
只是从原始对象的int
初始化的,归结为将原始int
的值复制到新int
中......
您的编译器无法区分深拷贝和浅拷贝,它甚至不知道"深拷贝"或"浅拷贝"应该是什么意思。在语言层面上,C++没有深拷贝或浅拷贝这样的东西。这些只是程序员常用的术语,用于讨论复制逻辑上(但不是物理上)包含其他对象的对象的不同方法......
- 无法在构造函数中执行设置元素插入
- 运算符 new 的执行顺序和构造函数的参数
- 在构造函数中删除后继续执行
- 在执行new期间是否可以在构造函数中传递不同的参数?
- 如果普通默认构造函数不执行任何操作,为什么我们不能使用 malloc 创建平凡可构造的对象?
- 如何执行参数化构造函数的调用?
- 显式构造函数仍在执行转换
- 遵循 C++ 中的构造函数执行顺序
- 模板化构造函数无法执行转换
- 如果默认构造函数不执行任何操作,则目的是什么
- 复制构造函数如何执行?
- 使用构造函数的可变参数中的其他模板化类执行模板化类的初始化
- 如何为基类构造函数中的每个子类执行特定任务
- Arduino 上的 Sketch 停止在对象构造函数中执行
- 具有模板参数推导的构造函数意外执行
- 将执行哪个构造函数
- C++:程序的执行(构造函数、析构函数、赋值运算符等)
- C++类组合 - 何时执行构造函数和析构函数
- 在C++中执行构造函数
- C++ 此指针不执行构造函数