浅拷贝的问题

本文深入探讨了C++中深拷贝与浅拷贝的区别及其应用场景。特别关注当类包含指针成员时如何正确实现拷贝构造函数以避免内存泄漏问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 
 1 #include <unistd.h>
 2 #include <stdlib.h>
 3 #include <stdio.h>
 4 #include <fcntl.h>
 5 #include <error.h>
 6 #include <iostream>
 7 #include <string>
 8 using namespace std;
 9 class A{
10    int i;
11 };
12 class B{
13    A *p;
14 public:
15    B(){p=new A;}
16    ~B(){delete p;}
17    /*
18    B(const B& ths){
19        p = ths.p;
20    }*/
21 };
22 void sayHello(B x){
23 }
24 int main(){
25    B b;
26    sayHello(b);
27 }
View Code
这里的错误原因是编译器在生成default copy construction的时候使用的bitwise copy语义,也就是只是简单的浅拷贝。 上面被注释掉的程序就是编译器自动添加的部分。 从而导致在sayHello中向参数x传递值时,调用了bitwise copy的拷贝构造函数,使得x对象和b对象中的值完全一致,包括p指针的值,在x离开作用域(也就是sayHello函数结束),x发生析构,调用delete 销毁了指针p,同时在main函数结束的时候,析构b时又会调用一次delete删除指针p。
也就是本程序会delete一直已经被delete 的指针。可以做如下改进,来修复程序:
 1 #include <unistd.h>
 2 #include <stdlib.h>
 3 #include <stdio.h>
 4 #include <fcntl.h>
 5 #include <error.h>
 6 #include <iostream>
 7 #include <string>
 8 using namespace std;
 9 class A{
10    int i;
11 };
12 class B{
13    A *p;
14 public:
15    B(){p=new A;}
16    ~B(){delete p;}
17    B(const B& other){
18        p = new A;       //构建新的指针
19        *p = *(other.p); //将指向的内容复制,依然指向不同的位置
20    }
21 };
22 void sayHello(B b){
23 }
24 int main(){
25    B b;
26    sayHello(b);
27 }
View Code

 

 
注释:
以下三种情况需要用到拷贝函数:
a)一个对象以值传递的方式传入函数体;
b)一个对象以值传递的方式从函数返回;
c)一个对象需要通过另外一个对象进行初始化。
 
作为实参传递给非引用类型的形参,会调用拷贝构造函数,默认的是浅拷贝,涉及到指针时会有大问题
 
 
 1 #include <unistd.h>
 2 #include <stdlib.h>
 3 #include <stdio.h>
 4 #include <fcntl.h>
 5 #include <error.h>
 6 #include <iostream>
 7 #include <string>
 8 using namespace std;
 9 class A{
10    int i;
11 };
12 class B{
13    A *p;
14 public:
15    B(){p=new A;}
16    ~B(){delete p;}
17    /*
18    B(const B& ths){
19        p = ths.p;
20    }*/
21 };
22 void sayHello(B &x){//引用
23 }
24 int main(){
25    B b;
26    sayHello(b);
27 }
View Code

 

 
主要考察“浅拷贝”和“深拷贝”。
大多情况下“浅拷贝”可以满足需求 ,但是一旦对象存在了动态成员,那么浅拷贝就会出问题了,为了防止编译器默认浅拷贝的发生,可以声明一个私有的拷贝构造函数, 甚至不必去定义这个拷贝构造函数,这样因 为拷贝构造函数是私有的,如果用户试图按值传递或函数返回该类对象,将得到一个编译错误,从 而可以避免按值传递或返回对象。

转载于:https://www.cnblogs.com/guxuanqing/p/5933949.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值