第 13 章 拷贝控制

2019-06-27  本文已影响0人  cb_guo

13.1 拷贝、赋值与销毁

13.1.1 拷贝构造函数

拷贝初始化
string dots(10, '.');    // 直接初始化
string s(dots);         // 直接初始化
string s2 = dots;       // 拷贝初始化
string null_book = "9-999-99999-9";     // 拷贝初始化
string nines = string(100, '9');        // 拷贝初始化
参数和返回值

13.1.2 拷贝赋值运算符

Sales_data trans, accum;
trans = accum;   // 使用 Sales_data 的拷贝赋值运算符
重载赋值运算符
class Foo{
    public:
        Foo& operator=(const Foo&);  // 赋值运算符
        // ....
};
A& operator= (const A& a){ //拷贝赋值运算符
    val = a.val;
    return *this;
}

13.1.3 析构函数

class Foo{
    public:
        ~Foo();  // 析构函数
        // ...
};

13.1.4 三/五法则

13.1.5 使用 =default

13.1.5 阻止拷贝

定义删除的函数
struct NoCopy{
    NoCopy () = default;    // 使用合成的默认构造函数
    NoCopy (const NoCopy&) = delete;    // 阻止拷贝
    NoCopy &operator=(const NoCopy&) = delete;   // 阻止赋值
    ~NoCopy() = default;   // 使用合成的析构函数 
};
析构函数不能是删除的函数
struct NoDtor{
    NoDtor () = default;   // 使用默认构造函数
    ~NoDtor() = delete;   // 我们不能销毁 NoDtor 类型的对象
}
NoDtor nd;  // 错误:NoDtor 的析构函数是删除的
NoDtor *p = new NoDtor();    // 正确: 但我们不能 delete p
delete p;    // 错误: NoDtor 的析构函数是删除的
合成的拷贝控制成员可能是删除的
private 拷贝控制
class PrivateCopy{
    // 无访问说明符;接下来的成员默认是 private 
    // 拷贝控制成员是 private 的,因此普通用户代码无法访问
    PrivateCopy(const PrivateCopy&);
    PrivateCopy &operator=(const PrivateCopy&);
    // 其他成员
public:
    PrivateCopy() = default;   // 使用合成的默认构造函数
    ~PrivateCopy();    // 用户可以定义此类型的对象,但无法使用它们
};
建议:希望阻止拷贝的类应该使用 =delete 来定义它们自己的拷贝构造函数和拷贝赋值运算符,而不应该将它们声明为 private 的

13.2 拷贝控制和资源管理

13.2.1 行为像值的类 重点

13.2.2 定义行为像指针的类 重点

13.3 交换操作

#include<iostream>
using namespace std;

class AA{
    // 友元, 以便访问 AA 的 private 数据成员
    friend void swap(AA &l, AA &r);

    public:
        // 构造函数
        AA(int bb):aa(bb) {
            std::cout << aa << " 构造函数" << endl;
        }

        // 拷贝构造函数
        AA(const AA &temp){
            std::cout << temp.aa << " 拷贝构造函数" << endl;
            this->aa = temp.aa;
        }

        // 拷贝赋值运算符
        AA& operator=(const AA &temp){
            std::cout << " 拷贝赋值运算符" << endl;
            this->aa = temp.aa;
            return *this;
        }

        ~AA(){
            std::cout << aa << " 析构函数" << endl;
        }

    private:
        int aa;
};

// 内联函数
inline void swap(AA &l, AA &r){
    std::cout << "交换之前, l.aa = " << l.aa << ", r.aa = " << r.aa << endl;
    std::swap(l.aa, r.aa);
    std::cout << "交换完成, l.aa = " << l.aa << ", r.aa = " << r.aa << endl;
}

int main(){
    AA ff(11);   // 调用构造函数
    AA gg = ff;  // 调用拷贝构造函数
    AA hh(ff);   // 调用拷贝构造函数

    AA kk(77);   // 调用构造函数
    kk = ff;     // 调用拷贝赋值运算符

    AA a(11111);
    AA b(22222);
    swap(a, b);
}
11 构造函数
11 拷贝构造函数
11 拷贝构造函数
77 构造函数
 拷贝赋值运算符
11111 构造函数
22222 构造函数
交换之前, l.aa = 11111, r.aa = 22222
交换完成, l.aa = 22222, r.aa = 11111
11111 析构函数
22222 析构函数
11 析构函数
11 析构函数
11 析构函数
11 析构函数

13.4 拷贝控制示例

13.5 动态内存管理类

13.6 对象移动

13.6.1 右值引用

13.6.2 移动构造函数和移动赋值运算符

13.6.3 对象移动

上一篇下一篇

猜你喜欢

热点阅读