函数返回的临时对象不总是 r 值吗?

Posted

技术标签:

【中文标题】函数返回的临时对象不总是 r 值吗?【英文标题】:Is a function-returned temporary object not always r-value? 【发布时间】:2012-05-18 16:59:29 【问题描述】:
struct Test

    Test()
    

    Test(const Test& other)
    
        cout << "Copy" << endl;
    

    Test(Test&& other)  
    
        cout << "Move" << endl;
    
;

Test* f()

    static Test t;
    return &t;


int main()
   
    auto t = *f();
    return 0;

输出是:复制

*f() 显然是一个匿名临时对象,因此它应该是一个 r 值并且应该调用移动构造函数。为什么编译器会将*f() 视为左值?

是编译器的bug,还是我的理解有误?

【问题讨论】:

"*f() 显然是一个匿名临时对象,因此它应该是一个右值" 不,不是;你的假设是有缺陷的。 *f() 甚至不是一个对象,而是一个引用。 【参考方案1】:

f() 的结果是Test* 类型的匿名临时对象。 f() is an rvalue.

*f() 通过所述指针执行间接寻址。与使用间接运算符时一样,结果是左值。

【讨论】:

f() 的结果是Test* 类型的,而不是临时对象。标量临时变量在 C++ 中非常少见。我遇到它们的唯一地方是将42 传递给带有const int&amp; 参数的函数。【参考方案2】:

为什么编译器将 *f() 视为左值?

因为它一个左值。 operator* 应用于指针时的结果是总是 一个左值。而且你不能隐式地从左值移动。

记住运动的黄金法则:运动只有在保证安全的情况下才会发生(对于“保证”的特定定义)。

查看您的代码。您要从中移动的对象是否很明显将被破坏并且在移动后无法访问?如果没有,那么您必须使用std::move 离开它;这会告诉系统您要对因运动而发生的任何错误负责。

【讨论】:

【参考方案3】:

其实f()的返回是一个指针。取消引用指针不会导致新对象出现。但是,您正在将返回值指向的内存地址中的任何内容复制到t 中。在这种情况下,我当然希望得到一份副本。

【讨论】:

【参考方案4】:

"*f() 显然是一个匿名的临时对象..."

不,不是!它是一个静态对象。

【讨论】:

【参考方案5】:
Test f()

    return Test();


int main()
   
    auto t = f();
    return 0;

现在你正在返回一个匿名临时 - 线索是创建一个临时并按值返回它而不将它绑定到名称。

正如其他人正确指出的那样,您正在做的是返回一个指向静态(非临时)命名(非匿名)对象的指针。 pointer 可能是一个匿名的临时对象,但它指向 的东西不是。

【讨论】:

以上是关于函数返回的临时对象不总是 r 值吗?的主要内容,如果未能解决你的问题,请参考以下文章

为啥通过构造函数返回对象时没有临时对象?

为啥在这个例子中可以返回临时对象?

自制反汇编工具使用实例 其一

NSFetchedResultsController 总是包含临时对象

tempfile:临时文件系统对象

为啥非常量引用不能绑定到临时对象?