第五节 · 换一种变脸的方式 · 类型转换运算符定义

赋值运算符决定了对象如何被复制或移动。正确实现它们对于管理资源至关重要。


复制赋值运算符

class String
{
private:
    char* data;
    size_t length;
    
public:
    String(const char* s = "")
    {
        length = strlen(s);
        data = new char[length + 1];
        strcpy(data, s);
    }
    
    ~String()
    {
        delete[] data;
    }
    
    // 复制赋值运算符
    String& operator=(const String& other)
    {
        if (this != &other)  // 自赋值检查
        {
            delete[] data;   // 释放旧资源
            
            length = other.length;
            data = new char[length + 1];
            strcpy(data, other.data);
        }
        return *this;
    }
};

copy-and-swap 惯用法

更安全的实现方式:

优点:

  • 自动处理自赋值

  • 异常安全

  • 代码简洁


移动赋值运算符


五法则(Rule of Five)

如果定义了以下任何一个,通常需要定义全部:

  1. 析构函数

  2. 复制构造函数

  3. 复制赋值运算符

  4. 移动构造函数

  5. 移动赋值运算符


零法则(Rule of Zero)

如果类不直接管理资源,就不需要定义任何特殊成员函数。


default 和 delete


复合赋值运算符


自赋值安全


统一赋值运算符

使用 copy-and-swap,可以用一个运算符同时处理复制和移动:


习题

  • 解释 copy-and-swap 惯用法的优点。

  • 什么是五法则和零法则?

  • 为什么移动赋值运算符要标记 noexcept

Last updated