重载赋值运算符与提供隐式构造函数
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
的构造函数
- C c(5);调用以
int
作为参数的构造函数。
- C c = 5;以
int
作为参数调用 构造函数 。
- 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 的回答。
我刚刚在 C++ Primer(第 5 版)的第 563 页了解到可以重载赋值运算符。因此,如果我正在编写 class C
并且将整数分配给此 class 的对象是有意义的,那么我可以为赋值运算符提供 rhs
类型 int
。然后我的class的客户可以写:
C c;
...
c = 5;
问题:如果这样的赋值有意义,那么隐式构造函数C(int);
是否也应该有意义?如果是这样,那么我真的应该定义这个构造函数(它也有其他用途)并且永远不需要重载赋值运算符。我错过了什么吗?
你也不需要赋值运算符,只需要来自 int
- C c(5);调用以
int
作为参数的构造函数。 - C c = 5;以
int
作为参数调用 构造函数 。 - 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 的回答。