C++ 从函数返回时的右值引用行为
在以下代码中:C++ 从函数返回时的右值引用行为,c++,c++11,c++14,rvalue-reference,C++,C++11,C++14,Rvalue Reference,在以下代码中: class Myclass { public: Myclass() = default; ~Myclass() = default; Myclass(Myclass&&) = default; Myclass& operator=(Myclass&&) = default; Myclass(const Myclass&) = delete; Myclass&
class Myclass
{
public:
Myclass() = default;
~Myclass() = default;
Myclass(Myclass&&) = default;
Myclass& operator=(Myclass&&) = default;
Myclass(const Myclass&) = delete;
Myclass& operator=(const Myclass&) = delete;
};
Myclass GetObj()
{
Myclass obj;
return obj;
}
Myclass WrapperOfGetObj()
{
Myclass&& Wrapobj = GetObj();
return Wrapobj;
}
int main()
{
return 0;
}
编译时,函数WrapperOfGetObj
在return
Wrapobj
上出现错误。错误是
'Myclass::Myclass(const Myclass&)':尝试引用已删除的函数
这意味着它正试图调用deleted
copy构造函数。正如我所知,Wrapobj
是左值,当返回它时,它的行为应该与GetObj
方法中的obj
相同,即在返回时调用move构造函数。
那么它为什么要寻找复制构造函数呢?这里我遗漏了什么?这里的问题是(正如T.C.在注释部分总结的那样)wrapbj
是一个引用,而不是一个对象,因此隐式移动(即将返回的左值视为右值)在这种情况下不适用(请参阅)
您可以通过以下方式解决此问题:
Myclass Wrapobj = GetObj();
而不是当前的:
Myclass&& Wrapobj = GetObj();
或者在返回时显式地std::move()
ingWrapobj
。我个人建议选择第一个选项。您需要使用std::move()
显式生成右值。对于这个主题来说,这可能是一个很好的额外阅读。表达式Wrapobj
是类型为MyClass
的左值;表达式从来没有引用类型(在[expr]/5调整之后)。问题是隐式移动只适用于自动存储持续时间([class.copy]/32)的对象,而引用不是对象。此外,“如果返回语句中的命名左值的类型与函数的返回类型不同,则编译器不会将其视为右值”,这是不正确的,因为。@t.C.:这在标准中已经阐明了吗?在我更活跃的时候,我曾经相信这一点,但后来我想这可能取决于解释(见)。还有最后一句话吗?无论如何,我会尝试更准确地改写它。我认为当它立即消失时,考虑预调整类型是非常有用的(因此,括号限定符)。@ T.C:我写了一个。