重载赋值运算符与提供隐式构造函数

Overloading the assignment operator vs. providing an implicit constructor

我刚刚在 C++ Primer(第 5 版)的第 563 页了解到可以重载赋值运算符。因此,如果我正在编写 class C 并且将整数分配给此 class 的对象是有意义的,那么我可以为赋值运算符提供 rhs类型 int。然后我的class的客户可以写:

C c;
...
c = 5;

问题:如果这样的赋值有意义,那么隐式构造函数C(int);是否也应该有意义?如果是这样,那么我真的应该定义这个构造函数(它也有其他用途)并且永远不需要重载赋值运算符。我错过了什么吗?

你也不需要赋值运算符,只需要来自 int

的构造函数
  1. C c(5);调用以 int 作为参数的构造函数。
  2. C c = 5;以 int 作为参数调用 构造函数
  3. C c; c = 5;调用默认构造函数,第二条语句会调用构造函数给一个int,然后是赋值运算符

(2) 会造成混淆。必须使用构造函数,因为对象不存在。

如果 C 定义了一个采用 int 的非 explicit 构造函数,那么你不一定 需要 一个采用 int 的赋值运算符int,但最终可能会更有效率。

如果operator=(int)存在:

C c; //default constructor
c = 5; //assignment from int

如果 C(int) 存在而 operator=(int) 不存在:

C c; //default constructor
c = 5; //construction of temporary from int, then assignment from C

如果移动语义对 C 有效,那么后者可能是可以接受的。如果不是,您可能仍要定义 operator=(int)。最终,这取决于许多因素,例如您分配给 C 的频率、副本的价格等。了解这些问题,找出它们如何应用于您的 class,然后选择最合理的方案。

Is it true that if such an assignment makes sense, then an implicit constructor C(int); should also make sense?

取决于。赋值和隐式构造器的区别在于,赋值时已经设置了一个对象,而隐式转换只需要创建一个给定int的对象。

在最常见的情况下,赋值运算符会忘记原始对象的所有数据。在这种情况下,您还应该能够将 int 转换为 C。但是,我可以想象赋值运算符实际上 使用 原始对象中的一些数据的情况。遇到这种情况,就想不到转换构造函数了

一个简单的例子:考虑数值模拟项目,它有 class Mesh — 在 space 中完成计算的一组点,和 class Field 这是该点的一组值(例如,该点的温度)。没有 Mesh 就不能存在 Field:

class Field {
    const Mesh& mesh;
    std::vector<int> data;
};

这里你不能创建Field(int)构造函数,因为你没有网格。但是,您可能会想到 Field::operator=(int) 赋值,它将用给定的 int 替换所有 data 值,保持 mesh 不变。

因此,第一个问题的答案是:,即使赋值有意义,转换并不总是有意义。

但是,如果这不是您的情况并且转换和赋值都有意义,那么请参考@TartanLlama 的回答。