c++ 对象模型 7

一:拷贝构造,深浅拷贝

class A{
public:
    int i;
    A(const A& tmpa){
        i = tmpa.i;
        cout << "拷贝构造函数被调用" <<endl;
    }
    A(){
        i = 0;
        cout << "构造函数被调用" <<endl;
    }
    ~A(){
        cout << "析构函数被调用" <<endl;
    }
    A(int value):i(value){  // 类型转换构造函数
        cout << "A(value) 构造函数被调用" <<endl;
    }
}
int main(){
    A a10(1000);  // 类型转换构造函数被调用
    A a11 = 1000;  // 类型转换构造函数被调用
    A a12 = A(1000); // 同上
    A a13 = (A)(1000);  // 同上
    /*
    A(value) 构造函数被调用
    A(value) 构造函数被调用
    A(value) 构造函数被调用
    A(value) 构造函数被调用
    析构函数被调用
    析构函数被调用
    析构函数被调用
    析构函数被调用
    */
}
/*
在vs2019的编译器中 对以上的代码进行了优化  在Linux的g++编译器输出如下:
A(value) 构造函数被调用
A(value) 构造函数被调用
拷贝构造函数被调用
析构函数被调用
A(value) 构造函数被调用
拷贝构造函数被调用
析构函数被调用
A(value) 构造函数被调用
拷贝构造函数被调用
析构函数被调用

析构函数被调用
析构函数被调用
析构函数被调用
析构函数被调用
*/
// 后三个调用的类型转换构造函数都会生成一个临时对象

A a10
//  这个代码在编译器中:
//A a10;  // 只定义对象不调用构造函数
//a10.A::A(1000);

A a11 = 1000;  
A a12 = A(1000); 
A a13 = (A)(1000);  
// 这三行代码在编译器中;
// A _a0 // 先定义一个临时对象
// _a0.A::A(1000);
// A a11;
// a11.A::A(_a0);  // 拷贝构造函数被调用
// _a0.A::~A();


A a11 = 1000; 
/*
    和后两行还是有一定的差别,先将1000转换成A对象(调用类型转换构造函数
    // explicit 拒绝隐式类型转换。 

*/
// 以上这些情况具体还是要看编译器时如何操作,具体是优化掉了类型转换构造函数还是没有优化


二 :拷贝构造函数是否必须有? (视情况而定
    1.如果你只有一些简单的成员变量类型, int double ,这种情况不需要拷贝构造函数
        编译器本身就支持成员变量的的copy。(bitwise copy  按位拷贝  (浅拷贝
    class A{
    public:
        int i;
        // A(const A& tmpa){
            // i = tmpa.i;
            // cout << "拷贝构造函数被调用" <<endl;
        // }
        A(){
            i = 0;
            cout << "构造函数被调用" <<endl;
        }
        ~A(){
            cout << "析构函数被调用" <<endl;
        }
        A(int value):i(value){  // 类型转换构造函数
            cout << "A(value) 构造函数被调用" <<endl;
        }
    }
    int main(){
        A mya;
        mya.i = 150;
        
        A mya2(mya);   // 编译器本身支持bitwise 拷贝
        cout << mya2.i <<endl;
        /*
            构造函数被调用
            150
            析构函数被调用
            析构函数被调用
        */
        
    }
// 这里 如果说写了自己的拷贝构造函数,那么就是告诉编译器不要执行bitwise copy
// 程序员本身来负责各个值的初始化

    2.当需要处理复杂的成员变量类型的时候需要些拷贝构造函数
    class A{
    public:
        int i;
        int *pm;
        // A(const A& tmpa){
            // i = tmpa.i;
            // cout << "拷贝构造函数被调用" <<endl;
        // }
        A(){
            i = 0;
            pm = new int(100);
            cout << "构造函数被调用" <<endl;
        }
        ~A(){
            delete pm;
            cout << "析构函数被调用" <<endl;
        }
        A(int value):i(value){  // 类型转换构造函数
            pm = new int(100);
            cout << "A(value) 构造函数被调用" <<endl;
        }
    }
    int main(){
    A mya;
    mya.i = 150;
        
    A mya2(mya);   
    cout << mya2.i <<endl;
            
    }
// 这里假设使用的是按位copy  那么mya2里面的指针也是指向mya的new开辟的地址
// 这时mya被析构掉,那么mya2的指针非法。所以这时候就需要写一个拷贝构造函数 

    3. 复杂的数据类型的拷贝构造函数
    class A{
    public:
        int i;
        int *pm;
        A(const A& tmpa){
            pm = new int(100);
            memcpy(pm, tmpa.pm, sizeof(int));
            // 这里使用的是深拷贝 彻底将对象的内容拷贝过来
            // 浅拷贝还是操作的同一个内存地址 
            
            i = tmpa.i;
            cout << "拷贝构造函数被调用" <<endl;
        }
        A(){
            i = 0;
            pm = new int(100);
            cout << "构造函数被调用" <<endl;
        }
        ~A(){
            delete pm;
            cout << "析构函数被调用" <<endl;
        }
        A(int value):i(value){  // 类型转换构造函数
            pm = new int(100);
            cout << "A(value) 构造函数被调用" <<endl;
        }
    }
    int main(){
    A mya;
    mya.i = 150;
        
    A mya2(mya);   
    cout << mya2.i <<endl;
            
    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值