为什么我的带有非const引用的构造函数允许使用临时对象调用?

时间:2011-06-07 16:06:31

标签: c++ most-vexing-parse

我在下面有一个示例代码。

#include<iostream>

template<typename T>
class XYZ
{
   private:
   T & ref;
   public:
   XYZ(T & arg):ref(arg)
   {
   }
};
class temp
{
   int x;
   public:
   temp():x(34)
   {
   }
};
template<typename T>
void fun(T & arg)
{
}
int main()
{
   XYZ<temp> abc(temp());
   fun(temp());  //This is a compilation error in gcc while the above code is perfectly valid. 
}

在上面的代码中,即使XYZ构造函数将参数作为非const引用,它编译也很好,而fun函数无法编译。这是特定于g ++编译器还是c ++标准必须说些什么呢?

编辑:

g ++ -v给出了这个。

gcc版本4.5.2(Ubuntu / Linaro 4.5.2-8ubuntu4)

2 个答案:

答案 0 :(得分:12)

 XYZ<temp> abc(temp());

它编译,因为它不是变量声明。我确定你认为它是一个变量声明,而事实是它是一个函数声明。函数的名称是abc;该函数返回一个XYZ<temp>类型的对象,并获取一个(未命名的)参数,该参数又是一个返回类型temp并且不带参数的函数。有关详细说明,请参阅以下主题:

并且fun(temp())无法编译,因为temp()创建了一个临时对象,而临时对象不能绑定到非const引用。

所以修复就是这样:将你的功能模板定义为:

template<typename T>
void fun(const T & arg) //note the `const`
{
}

答案 1 :(得分:5)

不,标准不允许将临时传递给非const引用。 (C ++ 0X在某些受控情况下引入了rvalue引用以允许这种情况),参见8.5.3 / 5(这对我来说太长了,有意义的部分是否则,引用应该是非volatile const type ,但你必须阅读整个案例列表才知道它们不适用于此处。)

并且

XYZ<temp> abc(temp());

只是另一个最令人烦恼的解析的例子。