提问人:overhaul_ 提问时间:8/3/2020 最后编辑:overhaul_ 更新时间:8/3/2020 访问量:293
复制构造函数 + 浅层和深度复制
Copy constructor + Shallow & deep copy
问:
我想问的是,当我没有显式编写任何复制构造函数时,编译器会自动生成默认执行浅层复制的复制构造函数,对吗? 因此,在 main() 程序中,当我更改整数 a、b 和指针 p 的值时,只有 p 的值发生了变化,而 a 和 b 的值在复制的对象中保持不变。为什么 a 和 b 的值也没有改变?我的代码是:
#include <iostream>
#include <string.h>
using namespace std;
class Dummy {
private:
int a, b;
int *p;
public:
Dummy() {
p = new int;
}
void setData(int x, int y, int z) {
a = x;
b = y;
*p = z;
}
void showData() {
cout << "a = " << a << " b = " << b;
cout << " p = " << *p << endl;
}
~Dummy() {
delete p;
}
};
int main() {
Dummy d1;
d1.setData(3, 4, 5);
Dummy d2 = d1;
d1.showData();
d2.showData();
d1.setData(6, 7, 8);
d1.showData();
d2.showData();
return 0;
}
我的程序的输出是:
a = 3 b = 4 p = 5
a = 3 b = 4 p = 5
a = 6 b = 7 p = 8
a = 3 b = 4 p = 8
我要说的是,当我更改对象 d2 的值时,对象 d1 的指针发生了变化,那么为什么对象 d2 的 a 和 b 的值没有改变呢?
此外,我在析构函数中使用 delete 关键字来删除动态分配的指针:
~Dummy() {
delete p;
}
但它反而使我的程序崩溃。为什么?
答:
你完全错了——.实际上,它本身没有任何所谓的东西。所以,调用某物是.光是这些词的使用也创造了很多。The idea of shallow copy
c++
deep copy
shallow copy
a bit wrong
shallow copy
confusion
现在,让我解释一下,当执行时会发生什么. 或者(在复制结构时)有一个叫做 的概念。在这个概念中,.现在,就是这样,.实际上,有他们的,当然,占据了.对于你,我写了一些关于记忆力的测试。如果你只看到测试及其输出,你会完全理解:cpp
initialization using assignment
cpp
c
bitwise copy
all the member variables of one object(struct object/class object - you can say either) is identically copied to another object
totally wrong idea
both objects point to same memory location
both object
own memory location
their variables
different memory spaces
#include <iostream>
#include <string.h>
using namespace std;
class Dummy {
int a, b;
int *p;
public:
Dummy() {
p = new int;
}
void setData(int x, int y, int z) {
a = x;
b = y;
*p = z;
}
void showData() {
cout << "a = " << a << " b = " << b;
cout << " p = " << *p << endl;
cout << endl; // an extra new line for readability of output
}
void showMemory() {
cout << "addr(a) = " << &a << " addr(b) = " << &b;
cout << " addr(p) = " << &p << endl;
}
~Dummy() {
*p = 100;
delete p;
}
};
// testing memory
void memoryTest() {
cout << "testing d1:" << endl;
Dummy d1;
d1.setData(3, 4, 5);
cout << "addr(d1) = " << &d1 << endl;
d1.showMemory();
cout << endl ;
cout << "testing d2:" << endl;
Dummy d2 = d1;
cout << "addr(d2) = " << &d2 << endl;
d2.showMemory();
}
int main() {
// memoryTest
memoryTest();
return 0;
}
测试的结果是:
testing d1:
addr(d1) = 0x6dfed4
addr(a) = 0x6dfed4 addr(b) = 0x6dfed8 addr(p) = 0x6dfedc
testing d2:
addr(d2) = 0x6dfec8
addr(a) = 0x6dfec8 addr(b) = 0x6dfecc addr(p) = 0x6dfed0
这清楚地表明,这两个物体所占据的记忆是完全不同的。d1
d2
- 现在,您可能还有另一个问题:那么,为什么当我写
*p=8
时,它会影响d1
和d2
?
当您分配时,我们可能会说发生了如下所示的事情(尽管,在应用按位复制时实际上并没有发生,只是为了清楚起见):Dummy d2 = d1;
d2.p = d1.p
所以,我们知道,并且包含相同的内存位置(注意:d1.p 是一个指针,因此,它不包含任何整数,而是包含 int 的内存地址)。d1.p
d2.p
因此,当您编写 时,您告诉程序转到 p 所针对的内存位置,并将该内存位置的值更改为 8。(请注意,在这里,您没有更改 的内容,仍然包含相同的内存位置,而是将该内存位置的内容从 5 更改为 8)。这就是为什么当你调用时,你会得到更改后的值。cause,包含与 相同的内存位置。*p = 8
d1.p
d1.p
d2.p
d2.p
d1.p
- 现在,可能还有一个问题:为什么当你在析构函数中释放
p
时,你的代码会崩溃?
现在,让我先问你,你能释放一个已经释放的记忆吗?您可以编写代码,但行为是未定义的。它可能会使您的程序崩溃,或者它可能什么都不做。
好吧,在你写的.现在,要么要么首先被摧毁。让我们假设,被摧毁了.所以,当驱逐舰被召唤时,是.然后,驱逐舰将被召唤,它也会尝试.但已经被释放了。在您的情况下,由于这个原因,程序会遇到崩溃。Dummy
destructor
delete p;
d2
d1
d2
first
d2's
p
freed
d1's
free p
p
希望,现在一切都清楚了。
如果对我上面描述的内容有任何不清楚的地方,请提出问题,我也会尽力回答。
评论
a
d
p