是函数返回的临时对象,并不总是 r 值

Is a function-returned temporary object not always r-value?

本文关键字:函数 返回 临时对象      更新时间:2023-10-16
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()视为 l 值?

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

f() 的结果是 Test* 类型的匿名临时对象。 f()是一个右值。

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

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

因为它l值。运算符 * 应用于指针时的结果始终是 l 值。而且您不能隐式地从 l 值移动。

记住运动的黄金法则:只有在保证安全的情况下才能发生运动(对于">保证"的某个定义(。

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

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

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

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

Test f()
{
    return Test();
}
int main()
{   
    auto t = f();
    return 0;
}

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

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