【问题标题】:why must you provide the keyword const in operator overloads为什么必须在运算符重载中提供关键字 const
【发布时间】:2010-06-01 13:09:53
【问题描述】:

只是好奇为什么在操作重载时参数必须是常量

CVector& CVector::operator= (const CVector& param)
{
  x=param.x;
  y=param.y;
  return *this;
}

难道你不能轻易做到这样的事情吗??

CVector& CVector::operator= (CVector& param) //no const
{
  x=param.x;
  y=param.y;
  return *this;
}

当某些东西变成 const 时,它在应用程序的剩余生命周期中是不可更改的吗?这在操作重载上有什么不同???

【问题讨论】:

    标签: c++ c visual-studio visual-studio-2008 visual-c++


    【解决方案1】:

    你不需要 const:

    @numerical25: 只是好奇为什么在操作重载时参数必须是 const

    这不是必需的,但这是一个很好的设计决策。

    参见 C++ 标准第 12.8-9 节:

    用户声明的副本分配 operator X::operator= 是非静态的 类的非模板成员函数 X 只有一个类型的参数 X, X&, const X&, volatile X& 或 const 不稳定的X&


    我认为这是个好主意:

    在我看来,使用 const 参数确实是一个合乎逻辑的设计决定,因为您希望确保其他值不会被更改。

    它告诉其他使用你的类的人,当你说类似myObject = other; 时,你不会更改other 的值,它会强制执行此操作,因此你不会意外更改other

    此外,如果您允许将对象的非 const 引用作为参数,那么您将限制可以使用您的函数的对象的数量。如果是 const,它可以用于 const 和非 const 的参数。如果您的参数是非常量,则它只能由非常量的参数使用。


    const 仅适用于当前引用,不适用于对象:

    @numerical25: 不是当某些东西变成 const 时,它在应用程序的剩余生命周期中是不可改变的吗?这在操作重载上有什么不同???

    一个 const 引用就是一个 const 引用。它不会改变你传入的实际对象的常量。


    一个非常量运算符重载的例子:

    这是一个参数不是 const 的运算符重载示例。
    我不建议这样做:

    class B
    {
    public: 
     const B& operator=(B& other)
     {
      other.x = 3;
      x = other.x;
      return *this;
     }
    
     int x;
    };
    
    
    void main(int argc, char** argv[])
    {
     B a;
     a.x = 33;
     B b;
     b.x = 44;
     a = b;//both a and b will be changed
     return 0;
    }
    

    【讨论】:

    • 声明的范围是const,而不是应用程序的生命周期。
    • @CuppM:是的,这是暗示的,因为整个引用变量本身也超出了范围。但是,它不会在其作用域内改变原始对象的 const-ness。例如,如果您有 2 个线程。
    【解决方案2】:

    const 参数在使用它的整个函数中都是 const,它不会在它之外改变它的 const 性。

    在这种情况下,您要声明一个 const 参数,以便您的赋值运算符同时接受非常量变量和 const 变量;特别是后一种情况,包括表达式的结果,它是一个临时 const 变量,您通常希望在赋值中支持它。

    【讨论】:

    • O,你是说 g = (a+b*c) 右边的结果被认为是一个常数??当您说 const 只是函数中的 const 时。您是说一旦该功能执行完毕。这些值将能够再次更改??
    • 你知道吗。现在确实有意义。如果我将 const 值转换为变量。这不会使变量成为 const,它只是意味着它现在拥有可以更改的 const 的值
    • @numerical,请记住,您的想法只有在引用传递时才能像您提到的那样起作用。
    【解决方案3】:

    如果你用过

    CVector& CVector::operator= (CVector& param) // no const
    

    然后这样做:

    const CVector& my_vector = GetMyVector();
    some_other_vector = my_vector; // call assignment operator - error!
    

    您会收到错误消息,因为 my_vectorconst CVector& 并且不能转换为 CVector&(非常量引用)。它只是在 const 的 operator= 函数中对它的本地引用,而不是整个对象本身。

    【讨论】:

      【解决方案4】:

      您可以使用非常量变量,但这有两种影响,一种是函数式的,另一种是关于您作为函数的编写者告诉用户的内容。

      1) 调用采用非常量引用的函数的人将无法使用 const 变量调用它

      2) 当你有一个非常量引用的函数参数时,你是在发出信号,“我保留更改它的权利”。通常,当您的函数的用户编写 a = b; 时,他并不希望 b 发生变化。

      请注意,您可以为此使用第三个选项,即按值传递:

      CVector& CVector::operator= (CVector param) //no reference
      

      这没有我上面提到的任何一个问题。但是,它的效率非常低。由于这三个因素,通过引用传递到 const 是首选,尤其是在复制成本高昂的向量等情况下。

      【讨论】:

        【解决方案5】:

        出于同样的原因,您将在任何地方使用 const:以确保将来对方法的更改不会无意中修改传入的参数,以帮助记录接口以通知调用者可以安全地传递参数而没有风险更改,并允许调用者传入在调用代码中声明为 const 的引用。

        【讨论】:

          【解决方案6】:

          另一个原因是允许转换。例如:

          string s = "foo";
          s = "bar";
          

          这里,一个实现可能选择只提供一个赋值运算符,它将一个对字符串的 const 引用作为参数,并依赖于编译器使用构造函数从 char * "bar" 创建一个临时字符串。如果 op= 的参数不是 const,这将不起作用,因为您无法将临时值绑定到非 const 引用。

          【讨论】:

            【解决方案7】:

            const 限定符使传递的参数(在您的示例中为“const CVector& param”)为只读。 const 限定符确保参数 (param) 在 operator=() 方法内不会被更改。

            没有 const 限定符,以下是可能的:

            CVector& CVector::operator= (CVector& param)
            {
              x=param.x;
              y=param.y;
            
              param.x = 10; // some random value
              param.y = 100;
            
              return *this;
            }
            

            上述方法在将值分配给左侧操作数后更改右侧操作数“param”。 const 限定符可帮助您不违反赋值操作的语义。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-05-09
              • 2017-07-20
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-11-19
              • 1970-01-01
              相关资源
              最近更新 更多