索引:
1. 编译器自动生成的拷贝构造函数是值拷贝(浅拷贝)。
2. 生成的析构函数是空实现。
3. 拷贝构造函数(参数采用引用为什么不直接用对象)
——————————————————————————————————————————
1. 编译器自动生成的拷贝构造函数是值拷贝(浅拷贝)。(两次析构函数的执行,析构的都是同一块内存,或者说“p指针”delete了两次)。
class class_B25
{
private:
int a25;
int *p25;
public:
class_B25();
~class_B25();
};
class_B25::class_B25(){
p25 = new int[1];
printf("声明的默认构造函数\n");
}
class_B25::~class_B25(){
delete []p25;
p25 = NULL;
}
void test_25_02(){
class_B25 class_b25_01;
class_B25 class_B25_02(class_b25_01);//调用编译生成的拷贝构造函数。
}
输出结果:
程序崩溃,
...
7ffea134b000-7ffea136c000 rw-p 00000000 00:00 0 [stack]
7ffea1370000-7ffea1372000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
已放弃
自己写拷贝构造函数(参数采用引用)(深拷贝),程序正确执行。
class class_C25
{
private:
int a25;
int *p25;
public:
class_C25();
~class_C25();
class_C25(const class_C25 &a);
};
class_C25::class_C25(){
p25 = new int[1];
printf("自定义默认构造函数\n");
}
class_C25::~class_C25(){
delete []p25;
p25 = NULL;
printf("自定义析造函数\n");
}
class_C25::class_C25(const class_C25 &a){
a25 = a.a25;
p25 = new int[1];//深拷贝,为新实例化的对象分配新的内存,而不是像“值拷贝”一样共用一块内存。
printf("自定义拷贝构造函数\n");
}
void test_25_03(){
class_C25 class_c25_01;
class_C25 class_C25_02(class_c25_01);
}
输出结果:
自定义默认构造函数
自定义拷贝构造函数
自定义析造函数
自定义析造函数
2. 生成的析构函数是空实现。由1可知,编译器为类生成的拷贝构造是值拷贝,如下代码,也会执行两次析构,可程序没有崩溃。侧面证明了,编译为类生成的析构函数式“空实现”。
class class_D25
{
private:
int a25;
int *p25;
public:
class_D25();
};
class_D25::class_D25(){
p25 = new int[1];
printf("自定义默认构造函数\n");
}
void test_25_04(){
class_D25 class_d25_01;
class_D25 class_d25_02(class_d25_01);
}
3. 拷贝构造函数(参数采用引用为什么不直接用对象)
首先当拷贝构造函数参数不是引用类型时,编译无法通过。
分析:拷贝构造函数的参数是非引用类型时,是值传递,那么函数就需要生成一个副本,再次调用拷贝函数,这样就会造成无限循环。(当然首先编译也是无法通过的)
参考: c学习38