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

Xan*_*lip 9 c++ proxy-classes facade pass-by-reference

我有下面这段代码,作为一个例子,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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

MSN*_*MSN 12

根据斯蒂芬的建议,你应该看一下非const引用如何不能绑定到临时对象的答案并简单地添加一个返回引用的成员函数dec_proxy,例如:

dec_proxy &ref() { return *this; }

并致电foo:

foo(
    dec_proxy<int>(i).ref(), 
    dec_proxy<double>(j).ref(), 
    dec_proxy<short>(k).ref());
Run Code Online (Sandbox Code Playgroud)

我很确定编译.


Jef*_*rey 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中的参数有效.