2
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()其视为左值?

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

4

5 回答 5

14

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

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

于 2012-05-18T17:04:27.763 回答
8

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

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

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

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

于 2012-05-18T17:04:10.080 回答
3

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

于 2012-05-18T17:03:12.873 回答
1

“*f() 显然是一个匿名的临时对象……”

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

于 2012-05-18T17:00:55.450 回答
0
Test f()
{
    return Test();
}

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

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

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

于 2012-05-18T17:08:19.817 回答