在 C++ 中将临时变量作为非常量引用传递;
我有以下代码片段,例如 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 的专门实例 - 这似乎是一种非常混乱且有限的方法。
我的问题是:将这种短暂的临时变量作为非常量引用参数传递的正确方法是什么?
I have the following piece of code, as an example dec_proxy attempts to reverse the effects of the increment operator upon the type that is executed in a complex function call foo - which btw I cannot change the interface of.
#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;
}
The problem is that for the various types I'd like to use dec_proxy I currently require creating a specialized instance of dec_proxy - it seems like a very messy and limited approach.
My question is: What is the correct way to pass such short-lived temporaries as non-const reference parameters?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
采纳斯蒂芬的建议,您应该查看 为什么非常量引用不能绑定到临时对象? 只需添加一个返回引用的成员函数
dec_proxy
,例如:dec_proxy &ref() { return *this; }
并调用
foo
:我很确定可以编译。
Taking Stephen's advice, you should look at the answer to How come a non-const reference cannot bind to a temporary object? and simply add a member function that returns a reference
dec_proxy
, e.g.:dec_proxy &ref() { return *this; }
and call
foo
:I'm pretty sure that compiles.
我认为通过添加函数模板
template是不正确的dec_proxy_impl& dec_proxy(T&t)
。它所做的只是欺骗编译器。它将导致运行时错误。函数 foo 需要 lvaue 或左值引用。但是
templatedec_proxy_impl& dec_proxy(T&t)
不返回有效的左值引用。在实现中,它创建一个临时对象并返回它。函数调用完成后,临时对象将被销毁。因此传递给函数foo
的值引用是错误的。实际上引用的对象已经被销毁了。++t;++s;++r
正在尝试访问无效对象。该行为是未定义的。MSN的解决方案是正确的。对象
dec_proxy(i)
的生命周期是从其声明到函数调用结束。它确保函数 foo 中的参数有效。I don't think it is correct by adding the function template
template<typename T> dec_proxy_impl<T>& dec_proxy(T&t)
.What it did is just cheating compiler. It will result in runtime error. The function
foo
requires the lvaue or lvalue reference. Buttemplate<typename T> dec_proxy_impl<T>& dec_proxy(T&t)
doesn't return a valid lvalue reference. In the implementation, it creates a temporary object, and returns it. After the function call finishes, the temporary object will be destroyed. So the value reference passed into the functionfoo
is wrong. Actually the referenced object has already been destroyed. The++t;++s;++r
are trying to access the invalid objects. The behavior is undefined.The solution from MSN is correct. The life time of the object
dec_proxy<int>(i)
is from its declaration to the end of the function call. It makes sure the parameter in the function foo is valid.您尝试做的是将右值(您的 new dec_facade(i))作为左值引用传递,这解释了为什么它不起作用。
如果编译器支持它,您可以使用右值引用,使用
&&
类型修饰符:(可以通过打开 C++0x 或 C++11 [部分] 支持来启用对右值引用的支持)
但这只是问题的一部分。您尝试做的是预先增加一个临时值!这是无意义的,因为在调用之后它就不会存在。你的对象将被增加,然后被销毁。
另一种解决方案是从函数定义中删除
&
,这将允许它接受任何参数。但这也许不是您想要的。What you try to do is to pass a rvalue (your
new dec_facade<int>(i)
) as an lvalue reference, which explains why it doesn't work.If you compiler support it, you can use rvalue references, using
&&
type modifier :(Support for rvalue reference could be enabled by switching on C++0x or C++11 [partial] support)
But that only one part of the problem. What you try to do, is to pre-increment a temporary value! That's non-sense, as it won't live after that call. Your object will be increment, then destroyed.
One other solution would be to remove the
&
from your function definition, which would permit it to accept any parameter. But that's perhaps not what you want.