在 C++ 中编写复制构造函数和赋值运算符的清单
-
03-07-2019 - |
题
请写出 C++ 中复制构造函数和赋值运算符需要执行的任务列表,以保持异常安全、避免内存泄漏等。
解决方案
首先确保你真的需要支持副本。大部分时间情况并非如此,因此禁用两者是可行的方法。
有时,您仍然需要在多态层次结构中为类提供重复,在这种情况下:禁用赋值运算符,编写(受保护的?)复制构造函数,并提供虚拟clone()函数。
否则,如果您正在编写一个值类,那么您将回到Coplien的正交规范形式的土地上。如果你有一个不能轻易复制的成员,你需要提供一个拷贝构造函数,一个析构函数,一个赋值运算符和一个默认构造函数。可以对此规则进行细化,例如:二大法则
我还建议您查看有关分配运算符的 C ++常见问题解答,以及复制和交换习语和 GOTW 。
其他提示
编译器生成的版本适用于大多数情况。
当您的对象包含 RAW 指针(不具有 RAW 指针的论点)时,您需要仔细考虑一下问题。所以你有一个RAW指针,第二个问题是你是否拥有该指针(它是否被你删除)?如果是这样,那么您将需要应用 4 的规则。
拥有超过 1 个 RAW 指针变得越来越难以正确执行(复杂性的增加也不是线性的[但这是观察性的,我没有真正的统计数据来支持该声明])。因此,如果您有超过 1 个原始指针,请考虑将每个指针包装在自己的类中(某种形式的智能指针)。
规则 4:如果一个对象是 RAW 指针的所有者,那么您需要定义以下 4 个成员以确保正确处理内存管理:
- 构造函数
- 复制构造函数
- 赋值运算符
- 析构函数
如何定义这些将取决于具体情况。但需要注意的事项:
- 默认结构:将指针设置为 NULL
- 复制构造函数:使用复制和交换思想提供“强异常保证”
- 赋值运算符:检查是否分配给 self
- 析构函数:防止从析构函数传播异常。
我在这里安全地不知道异常,但我这样做了。让我们想象它是一个模板化的数组包装器。希望它有所帮助:)
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;
}
不隶属于 StackOverflow