函数返回的临时对象不总是 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&
参数的函数。【参考方案2】:
为什么编译器将 *f() 视为左值?
因为它是一个左值。 operator* 应用于指针时的结果是总是 一个左值。而且你不能隐式地从左值移动。
记住运动的黄金法则:运动只有在保证安全的情况下才会发生(对于“保证”的特定定义)。
查看您的代码。您要从中移动的对象是否很明显将被破坏并且在移动后无法访问?如果没有,那么您必须使用std::move
离开它;这会告诉系统您要对因运动而发生的任何错误负责。
【讨论】:
【参考方案3】:其实f()
的返回是一个指针。取消引用指针不会导致新对象出现。但是,您正在将返回值指向的内存地址中的任何内容复制到t
中。在这种情况下,我当然希望得到一份副本。
【讨论】:
【参考方案4】:"*f() 显然是一个匿名的临时对象..."
不,不是!它是一个静态对象。
【讨论】:
【参考方案5】:Test f()
return Test();
int main()
auto t = f();
return 0;
现在你正在返回一个匿名临时 - 线索是创建一个临时并按值返回它而不将它绑定到名称。
正如其他人正确指出的那样,您正在做的是返回一个指向静态(非临时)命名(非匿名)对象的指针。 pointer 可能是一个匿名的临时对象,但它指向 的东西不是。
【讨论】:
以上是关于函数返回的临时对象不总是 r 值吗?的主要内容,如果未能解决你的问题,请参考以下文章