在C ++中将临时值作为非const引用传递

时间:2011-10-05 06:53:23

标签: c++ pass-by-reference proxy-classes facade

我有下面这段代码,作为一个例子,dec_proxy试图将增量运算符的效果反转到在复杂函数调用foo中执行的类型 - 顺便说一句,我无法改变它的接口。

#include <iostream>

template<typename T>
class dec_proxy
{
public:
   dec_proxy(T& t)
   :t_(t)
   {}

   dec_proxy<T>& operator++()
   {
      --t_;
      return *this;
   }

private:
   T& t_;
};

template<typename T, typename S, typename R>
void foo(T& t, S& s, R& r)
{
  ++t;
  ++s;
  ++r;
}

int main()
{
   int i = 0;
   double j = 0;
   short  k = 0;

   dec_proxy<int> dp1(i);
   dec_proxy<double> dp2(j);
   dec_proxy<short> dp3(k);

   foo(dp1,dp2,dp3);

   //foo(dec_proxy<int>(i),     <---- Gives an error
   //   dec_proxy<double>(j),     <---- Gives an error
   //   dec_proxy<short>(k));      <---- Gives an error 

   std::cout << "i=" << i << std::endl;

   return 0;
}

问题在于,对于我想使用dec_proxy的各种类型,我目前需要创建一个专门的dec_proxy实例 - 这似乎是一种非常混乱和有限的方法。

我的问题是:传递如此短暂的临时参数作为非const参考参数的正确方法是什么?

3 个答案:

答案 0 :(得分:12)

根据Stephen的建议,您应该查看How come a non-const reference cannot bind to a temporary object?的答案,然后添加一个返回引用dec_proxy的成员函数,例如:

dec_proxy &ref() { return *this; }

并致电foo

foo(
    dec_proxy<int>(i).ref(), 
    dec_proxy<double>(j).ref(), 
    dec_proxy<short>(k).ref());

我很确定编译。

答案 1 :(得分:7)

  

感谢MSN,解决方案:

我认为添加功能模板template<typename T> dec_proxy_impl<T>& dec_proxy(T&t)不正确。

它做的只是欺骗编译器。这将导致运行时错误。函数foo需要lvaue或左值引用。但是template<typename T> dec_proxy_impl<T>& dec_proxy(T&t)不会返回有效的左值引用。在实现中,它创建一个临时对象,并返回它。函数调用完成后,临时对象将被销毁。因此传递给函数foo的值引用是错误的。实际上引用的对象已被破坏。 ++t;++s;++r正在尝试访问无效对象。行为未定义。

来自MSN的解决方案是正确的。对象dec_proxy<int>(i)的生命周期是从它的声明到函数调用的结束。它确保函数foo中的参数有效。

答案 2 :(得分:2)

您尝试做的是将左值(您的new dec_facade<int>(i))作为左值参考传递,这解释了为什么它不起作用。

如果您的编译器支持它,您可以使用&&类型修饰符来使用右值引用: (可以通过打开C ++ 0x或C ++ 11 [partial]支持来启用对rvalue引用的支持)

template<typename T>
void foo(T& t)
{    
    ++t;
}
template<typename T>
void foo(T&& t)
{    
    ++t;
}

但这只是问题的一部分。你试图做的是预先增加一个临时值!这是无意义的,因为它不会在那个电话之后生活。你的物体会增量,然后被摧毁。


另一个解决方案是从函数定义中删除&,这将允许它接受任何参数。但那可能不是你想要的。

相关问题