C++: 拷贝管理

《C++ Primer》看到这一章我都惊呆了,C++竟然还能有这种功能:类可以控制该类型对象拷贝、赋值、移动和销毁时做什么。
以上操作通过:拷贝构造函数、移动构造函数、拷贝赋值运算符、移动赋值运算符、以及析构函数构成


拷贝构造函数:

定义: 如果一个构造函数的第一个参数是自身类类型的引用,且任何额外参数都有默认值,则此构造函数是拷贝构造函数。

本质上是个构造函数,所以它出现就会构造新对象,没有新对象它就没出现。

拷贝构造函数的第一个参数必须是一个引用类型,因为如果是值传递方式穿参的话,会立即再次调用拷贝构造函数,这样就形成无限递归了!危险!

如果我们没有自定义一个拷贝构造函数,编译器会自动帮我们合成一个。默认拷贝构造函数会将其参数成员逐个拷贝到正在创建的对象中。

以下情况会发生拷贝初始化:
1. 用=定义变量。
2. 将一个对象作为实参传递给一个非引用类型的形参。
3. 从一个返回类型为非引用类型的函数返回一个对象。
4. 列表初始化一个数组中的元素或一个聚合类中的成员。

有个小坑是,A aa = a;像这样定义并初始化一个A类型的变量aa,只会调用拷贝构造函数,不会调用拷贝赋值运算符。

#include <iostream>
using namespace std;

class A{
public:
    A(int i=0):n(i){}

    A(A &a, int i=0):n(i){
        cout<< a.getI() <<endl;
        cout<< getI() <<endl;
        cout<<"hello"<<endl;
    }

    const int getI(){
        return n;
    }

private:
    int n = 0;
};

int main(){
    A a(998);
    A b = a;//调用拷贝构造函数
    //输出结果为:
    //998
    //0
    //hello
    //证明 a 被当成了拷贝构造函数的第一个参数
    return 0;
}

拷贝赋值运算符

这其实就是个操作符重载。本质上是个名为operator=的函数,所有有形参有返回值,有函数体,都有。

当然要成为一个伟大的赋值运算符,当然要付出一点代价:
1. 名字必须是operator=
2. 必须定义为成员函数
3. 左侧运算对象就绑定到隐式的this参数上
4. 接受一个与其所在类相同类型的参数
5. 为了与内置类型的赋值保持一致,返回指向左侧对象的引用。

如果类没有定义自己的拷贝赋值操作符,编译器会自动生成一个。它会将右侧运算对象的每个非static成员赋予左侧运算对象的对应成员。


#include <iostream>
using namespace std;

class A{
public:
    A(int i=0):n(i){}

    A(A &a, int i=0):n(i){
        cout<< a.getI() <<endl;
        cout<< getI() <<endl;
        cout<<"hello"<<endl;
    }

    A &operator=(const A &r){
        n = r.n;
        cout<<"copying..."<<endl;
        return *this;
    }

    const int getI(){
        return n;
    }

private:
    int n = 0;
};

int main(){
    A a(998);
    A b(333);
    b = a;
    cout<< b.getI()<<endl;
    //copying...
    //998
    return 0;
}

析构函数:

析构函数释放对象使用的资源,并销毁对象的非static数据成员。

跟构造函数一样的是:没有返回类型,如果没自定义,编译器就会生成一个默认的。
跟构造函数不一样的是:没有构造函数初始化列表,名字是类名前加一个波浪号~,析构函数不接受参数,所以不能被重载,不能定义为delete。

note:析构函数先执行函数体,然后销毁成员,顺序按初始化的逆序。销毁一个内置类型的指针不会delete它指向的对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值