【问题标题】:Overloading the assignment operator vs. providing an implicit constructor重载赋值运算符与提供隐式构造函数
【发布时间】:2015-10-14 22:08:26
【问题描述】:

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

C c;
...
c = 5;

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

【问题讨论】:

  • 是的,有这样的构造函数很正常,很少定义除复制赋值或移动赋值之外的任何赋值运算符。

标签: c++ constructor operator-overloading assignment-operator


【解决方案1】:

如果C 定义了一个采用int 的非explicit 构造函数,那么您不一定需要一个采用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 的频率、副本的价格等。了解问题,弄清楚它们如何应用于您的课程,然后选择最合理的解决方案。

【讨论】:

    【解决方案2】:

    如果这样的赋值有意义,那么隐含 构造函数 C(int);应该也有意义吧?

    取决于。赋值和隐式构造函数的区别在于,赋值中已经有一个设置对象,而在隐式转换中,你必须创建一个只给定 int 的对象。

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

    一个简单的例子:考虑数值模拟项目,它有 Mesh 类——在其上完成计算的空间点集,以及 Field 类,它是这些点上的一组值(比如,那个点)。没有MeshField 就无法存在:

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

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

    所以,第一个问题的答案是:,即使赋值有意义,转换也不一定有意义。

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

    【讨论】:

      【解决方案3】:

      您也不需要赋值运算符,只需要来自 int 的构造函数

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

      (2) 可能会引起混淆。由于对象不存在,所以必须使用构造函数。

      【讨论】:

        猜你喜欢
        • 2020-09-06
        • 2014-10-12
        • 1970-01-01
        • 2017-01-21
        • 2011-02-16
        • 2021-07-27
        • 2013-03-26
        • 2011-05-19
        • 1970-01-01
        相关资源
        最近更新 更多