【问题标题】:temporaries not behaving as const临时人员的行为不像 const
【发布时间】:2011-11-16 09:08:03
【问题描述】:

在如下所示的表达式中,我不清楚临时假设是否为 const 类型。

#include <iostream>

class X {
public:
X(int a) { i = a; cout << "X(int) [" << (int)this << "]" << endl; }

X& operator+(const X& x) 
{ 
i += x.i; 
cout << "X operator+(const X&) [" << (int)this << "]" << endl; 
return *this; 
}

~X() { cout << "~X [" << (int)this << "]" << endl; }

private:
int i;
};


int main() 
{
X x = X(3) + X(4);
cout << "done" << endl;

return 0;
}

X(3) 的行为类似于 non-const(因为我可以调用 operator+,而 X(4) 的行为类似于 const(因为它需要 operator+ 中的 const 参数)。

有人可以澄清一下,正确的理解是什么?

【问题讨论】:

    标签: c++ constants temporaries


    【解决方案1】:

    当涉及到类类型时,当您创建一个 const 类型的临时对象时,该临时对象将是 const。当您创建一个非常量类型的临时对象时,该临时对象将是非常量的。就是这样。 IE。就确切的类型而言,const 和临时变量之间根本没有任何联系。临时类类型永远不会自己假设 const 。是你可以明确地对其施加 const。

    在您的示例中,X(3)X(4) 都不是 const。由于X(3) 不是 const,因此您可以在其上调用非常量方法。

    说您的X(4)“行为为 const”是不正确的。在您的示例中,没有任何迹象表明它“表现得像 const”。仅仅因为您能够用某物初始化 const 引用并不意味着某物是 const。

    在您的问题中,您声明您“需要 operator+ 中的 const 参数”。这是不正确的。 operator+ 中不需要 const argument。您的 参数 x 被声明为 const 引用。一个 const 引用可以很容易地绑定到 const 参数以及非 const 参数。在您的情况下,const 引用参数 x 绑定到非 const 临时参数 X(4)

    【讨论】:

    • 但正如我所提到的,operator+ 需要一个 const X& 参数才能编译。如果我只有 X& operator+(X& x),编译失败。
    • @Chethan:这是由引用的属性引起的,而不是由临时对象的属性引起的。在 C++ 中,只有 const 引用可以绑定到临时对象。非常量引用不能绑定到临时对象。临时变量本身是否为 const 根本不重要。
    • @Oli Charlesworth:这真的是关于参考,而不是关于临时。
    【解决方案2】:

    您可以致电非const 的临时成员。但是您不能将非const 引用绑定到临时对象。

    【讨论】:

    • 只是一点点,但这应该是“你不能用右值表达式初始化非常量引用”。非常有可能获得绑定到临时的非常量引用。 (例如,试试std::ostream&amp; s = std::ostringstream().flush();。)
    【解决方案3】:

    从历史上看,临时变量是右值,而右值不是(也不能是) 简历合格。此规则适用于非类类型或类 没有成员函数的类型;因为 const-ness 干预功能 重载决议,临时的 cv 限定必须是 保持。如果一个函数只返回X,那么临时是 not const,你可以在它上面调用非常量函数;如果 函数返回X const,那么临时是const,你不能 在它上面调用非常量函数。作为一般规则,它可能是 最好将类类型返回为const;即X const f(),而不是 比X f()。但肯定有例外,没有人这样做, 即使在更合适的情况下。最后, 在某些情况下,您无法指定 const-ness-function 样式类型转换,例如 - 语法不 提供一种指定 cv 限定符的方法(使用 typedef 除外)。

    您可能想查看以下代码的输出:

    class C
    {
        std::string myComment;
    public:
        C( std::string const& comment ) : myComment( comment ) {}
    
        void f()
        {
            std::cout << "Non const " << myComment << std::endl;
        }
    
        void f() const
        {
            std::cout << "Const " << myComment << std::endl;
        }
    };
    
    typedef C const CC;
    
    C
    c()
    {
        return C("function return value");
    }
    
    C const
    cc()
    {
        return C("function return value");
    }
    
    int
    main()
    {
        C("function style conversion").f();
        CC("function style conversion").f();
        c().f();
        cc().f();
    }
    

    【讨论】:

    • 我认为将类类型返回为 const 的建议现在已经过时了。在 C++11 中,这严重干扰了移动语义,它仅适用于非常量右值。
    • @KerrekSB 我不知道。我怀疑这取决于应用程序;返回 const 肯定会导致编译器捕获一些错误,这可能是一个强参数。另一方面,几乎没有人这样做,所以它会捕获的错误不会那么频繁。至于移动语义:实际上有多少类支持它们?我不确定它们是否那么重要。 (但同样,这取决于应用程序。)
    • 嗯...stringvector。任何标准库容器。 IO流?独特的指针。锁。嗯……
    【解决方案4】:

    在以下代码中:

    X x = X(3) + X(4);
    

    X(3) 创建一个临时非常量对象,该对象调用operator+,将另一个临时非常量对象X(4) 作为函数的常量引用参数传递。

    非常量对象可以作为常量对象(通过引用传递)传递给函数,但常量对象不能通过非常量引用传递给函数。这就是区别。

    【讨论】:

      猜你喜欢
      • 2014-07-04
      • 1970-01-01
      • 2017-04-18
      • 1970-01-01
      • 1970-01-01
      • 2013-05-17
      • 2014-07-21
      • 1970-01-01
      相关资源
      最近更新 更多