在 C++11 中,如何获取没有名称的临时左值?

Posted

技术标签:

【中文标题】在 C++11 中,如何获取没有名称的临时左值?【英文标题】:In C++11, how can I get a temporary lvalue without a name? 【发布时间】:2014-05-09 14:14:21 【问题描述】:

我有一个传统的 C 库和一个函数 (setsockopts) 需要一个指针参数。在 C++11 (gcc 4.8) 中,我可以在不初始化命名变量的情况下传递此参数吗?

我有以下不满意的解决方案:

#include <iostream>
#include <memory>

int deref(int const * p) return * p;

using namespace std;

int main() 
    int arg = 0; cout << deref(& arg) << endl;
    // works, but is ugly (unnecessary identifier)

    cout << deref(& 42) << endl;
    // error: lvalue required as unary ‘&’ operand

    cout << deref(& * unique_ptr<int>(new int(42))) << endl;
    // works, but looks ugly and allocates on heap

【问题讨论】:

cout &lt;&lt; deref(&amp; (const int&amp;) 42) &lt;&lt; endl; 【参考方案1】:

如果这真的很麻烦,我会为setsockopt 创建一个包装器(未经测试)

template <typename T>
int setsockopt(int socket, int level, int optname, const T& value) 
    return setsockopt(socket, level, optname, &value, sizeof(value));


...

setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, 1);

【讨论】:

“医生,我的头撞到墙上好痛!” “好吧,不要那样做!” +1【参考方案2】:

编写一个函数模板将右值转换为左值:

template<typename T>
T &as_lvalue(T &&val) 
    return val;

现在,使用它:

deref(&as_lvalue(42));

警告:这不会延长临时对象的生命周期,因此您不能在创建临时对象的完整表达式结束后使用返回的引用。

【讨论】:

如another answer 中的示例,一个执行此操作的函数模板,另外还为您应用&amp; 运算符,甚至可以窥视该运算符的任何用户覆盖,已经存在于标准库中... @Cheersandhth.-Alf 除了绕过operator&amp; 重载,我们不想那样做吗? @Yakk:绕过operator&amp; 的重载正是我想要做的。以及这个答案没有做什么。不了解你(复数)。【参考方案3】:

您可以将const 引用绑定到临时:

cout << deref(addressof<const int>(42)) << endl;

【讨论】:

嗯。这难道不是addressof 中的一个错误(即它可能应该确保它是用左值调用的)吗? @Cheers:出于同样的原因&amp; 不支持左值——很容易创建指向死对象的指针。 @Cheers “C++ 程序员必须一直处理有限的嵌套生命周期,没问题。” - “没问题”?我声称它是现代 C++ 中(如果不是)最大的错误来源之一。 我相信展示核心语言的方式来写这个deref(&amp;(const int&amp;)0);会很有帮助。 我希望读者明白,到目前为止,Billy 所说的一切在技术上都没有意义,而且到目前为止,这不可能是由于任何误解。

以上是关于在 C++11 中,如何获取没有名称的临时左值?的主要内容,如果未能解决你的问题,请参考以下文章

13.6对象移动

C++Expression的学习笔记

C++11 中的左值引用和右值引用的区别

C++11 左值右值右值引用详解

[转]C++11 左值右值右值引用详解

c ++使用临时对象右值初始化左值引用以及自动推导[重复]