代码之家  ›  专栏  ›  技术社区  ›  John Smith

C++中编写复制构造函数和赋值运算符的检查表

  •  18
  • John Smith  · 技术社区  · 16 年前

    请在C++中编写一个复制构造函数和赋值操作符需要做的任务列表,以保持异常安全,避免内存泄漏等。

    4 回复  |  直到 9 年前
        1
  •  15
  •   cmorse    9 年前

    首先,确保您确实需要支持copy。大多数时候情况并非如此,因此禁用这两种方法是可行的。

    有时,您仍然需要从多态层次结构中提供类上的重复,在这种情况下:禁用赋值运算符,写一个(受保护的?)复制构造函数,并提供一个虚拟clone()函数。

    否则,在编写一个值类的情况下,您将回到共有权的正交规范形式。如果您有一个不能被简单复制的成员,那么您需要提供一个复制构造函数、一个析构函数、一个赋值运算符和一个默认的构造函数。可以对该规则进行优化,例如请参见: The Law of The Big Two

    我也建议你看看 C++ FAQ regarding assignment operators copy-and-swap idiom 及AT GOTW .

        2
  •  4
  •   Loki Astari    16 年前

    编译器生成的版本在大多数情况下都可以工作。

    当您的对象包含一个原始指针(一个没有原始指针的参数)时,您需要更仔细地考虑这个问题。所以您有一个原始指针,第二个问题是您是否拥有该指针(它是否被您删除)?如果是这样,那么您需要应用4规则。

    拥有一个以上的原始指针变得越来越难正确执行(复杂度的增加也不是线性的[但这是观测性的,我没有真实的统计数据来支持该声明])。因此,如果您有一个以上的原始指针,请考虑将每个指针包装在自己的类中(某种形式的智能指针)。

    规则4:如果对象是原始指针的所有者,则需要定义以下4个成员以确保正确处理内存管理:

    • 构造函数
    • 复制构造函数
    • 分配运算符
    • 析构函数

    如何定义这些将取决于具体情况。但要注意的是:

    • 默认构造:将指针设置为空
    • 复制构造函数:使用复制和交换IDeum提供“强异常保证”
    • 分配运算符:检查是否分配给自己
    • 析构函数:防止异常从析构函数中传播。
        3
  •  1
  •   ugasoft    16 年前
        4
  •  -2
  •   Nazgob    16 年前

    我不知道这里有什么例外,但我走这条路。假设它是一个模板化数组包装器。希望有帮助:)

    Array(const Array& rhs)
        {
            mData = NULL;
            mSize = rhs.size();
            *this = rhs;
        }
    
        Array& operator=(const Array& rhs)
        {
            if(this == &rhs)
            {
                return *this;
            }
    
            int len = rhs.size();
    
            delete[] mData;
    
            mData = new T[len];
    
            for(int i = 0; i < len; ++i)
            {
                mData[i] = rhs[i];
            }
    
            mSize = len;
    
            return *this;
        }