何时提供用户定义的复制构造函数和赋值运算符
When to provide user-defined copy constructor and assignment operator?
当我们有指针数据成员时,我们只需要编写复制构造函数和赋值运算符(因为否则当编译器生成的复制 ctor 执行浅拷贝时,两个指针可能会指向同一个对象)?
如果我们所有的数据成员都分配在堆栈上,我们可以只依靠编译器定义的复制构造函数和赋值运算符吗?
指针无疑是最明显的情况,但不是唯一的情况。
另一个示例是在 ctor 中打开数据库连接并在 dtor 中关闭它的类。副本 ctor 需要执行一些操作来复制数据库连接,因此副本与数据库的连接与原始数据库的连接分开关闭。
如果编译器定义的复制构造函数有效,请使用它。浅拷贝通常更快,即使它们可能会处理指针地址而不是在某些情况下可能是您想要的指向数据。例如,您可能需要一个指向与代码的其他部分共享的纹理的指针。
仅当您需要数据副本时,才应修复复制构造函数。
警告将是成员变量,这些变量是具有自己的复制构造函数的类,不能为您提供有关当时发生的事情的任何承诺。
如果基类或类包含的对象没有复制构造函数(即流),那么如果您希望类可复制构造,则必须实现复制构造函数。
对于流情况,此复制构造函数可能必须
a) 复制文件,
b) 创建一个可以写入的新空文件,
c) 或保存流的地址,以便两个对象都可以写入它。
最后一个选项是最复杂的,可能需要使用 shared_ptr
.
一般来说,我喜欢把我所有的资源都放在维护这些资源的类中,这些 tesource 维护者需要一个复制构造、复制赋值和一个析构函数。根据资源的不同,可能会删除复制构造函数和复制赋值。
不太明显的是,一些不直接维护资源的类可能需要复制赋值:如果您希望复制赋值具有很强的异常安全性,则通常需要实现复制赋值。例如,假设您的类存储两个向量。生成的副本组合执行成员赋值。通常,成员分配是可以的。但是,如果对第二个向量的断言引发异常,则无法恢复原始状态!更好的副本组合如下所示:
T& T::operator= (T other) {
other. swap(*this);
return *this;
}
由于swap()
可以在不抛掷的情况下实现,因此这种性能具有很强的异常安全性。
- 为什么在使用转换构造函数赋值后调用C++类的析构函数?
- 为用户定义的类正确调用复制构造函数/赋值运算符
- C++:关于使用 Stroustrup 示例移动构造函数/赋值的问题
- 初始值设定项列表与构造函数赋值与变量定义
- std::vector::emplace() 真的在面对抛出移动构造函数/赋值运算符时提供了强大的异常保证吗?
- 创建一个类并在C++中使用构造函数(赋值)
- 如何为具有自引用指针的类实现复制构造函数/赋值运算符
- 使typedef的构造函数/赋值运算符成为友元函数
- 复制构造函数+赋值运算符
- C++ 矢量从构造函数赋值对象,无需临时
- 具有std::原子成员变量的类的复制构造函数/赋值运算符出错
- 初始化对象时复制构造函数/赋值运算符混淆
- 默认情况下是默认的构造函数/赋值noexcept/constexpr
- 是否为派生类生成的移动构造函数/赋值运算符
- 复制构造函数/赋值运算符
- C++复制构造函数/赋值运算符错误
- 正在获取要使用的移动构造函数/赋值运算符
- 私有复制构造函数/赋值运算符和复制初始化
- 如何为自定义字符串类型编写构造函数/赋值运算符重载
- 为什么C++允许在具有指针成员的类中编译默认的复制构造函数/赋值运算符重载