我想问的是,当我不显式编写任何副本构造函数时,编译器会自动生成默认情况下执行浅表复制的副本构造函数吗? 因此,在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
我的意思是,当我更改对象d1的值时,对象d2的指针发生了变化,那么为什么对象d2的a和b的值也没有变化?
我也在析构函数中使用delete关键字删除动态分配的指针:
~Dummy() {
delete p;
}
但是它使我的程序崩溃了。为什么呢?
答案 0 :(得分:2)
您完全错了-The idea of shallow copy
。实际上,c++
本身没有内置任何称为deep copy
的东西。因此,称shallow copy
为a bit wrong
。而且仅使用这些单词shallow copy
也会创建很多confusion
。
现在,让我解释一下,当cpp
执行initialization using assignment
时会发生什么。 cpp
或c
(在复制struct时)有一个称为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
和d2.p
包含相同的内存位置(注意:d1.p是指针。因此,它不包含任何整数,而包含的内存地址为一个int)。
因此,当您编写*p = 8
时,是在告诉程序转到p指定的存储位置,并将该存储位置的值更改为8。(请注意,此处您没有更改d1.p
,d1.p
的内容仍然包含相同的存储位置,只是您将该存储位置的内容从5更改为8)。这就是为什么当您调用d2.p
时会得到更改的值。原因,d2.p
与d1.p
包含相同的内存位置。
p
时代码会崩溃?:现在,让我首先问您,您可以释放一个已经释放的内存吗?您可以编写代码,但是行为是不确定的。它可能会使您的程序崩溃,也可能什么都不做。
好吧,您在Dummy
destructor
中写了delete p;
。现在,d2
或d1
将首先被销毁。假设d2
被销毁了first
。因此,当调用d2's
驱逐舰时,p
是freed
。然后,将调用d1's
驱逐舰,并且还将尝试free p
。但是p
已被释放。就您而言,由于这个原因,程序会崩溃。
希望,现在一切都清楚了。
如果我对上述内容不清楚,请提出问题,我也会尽力回答。