正如预期的那样,以下代码无法编译
#include <iostream>
class A
{
public:
A() = default;
~A() = default;
A(const A&) = delete;
A(A&&) = delete;
A& operator=(const A&) = delete;
A& operator=(A&&) = delete;
A& operator<<(const int i)
{
std::cout << "operator<< called" << std::endl;
return *this;
}
};
void foo(A&& a)
{
std::cout << "foo called" << std::endl;
}
int main()
{
A a; a << 14;
foo(std::move(a)); // works fine
foo(A() << 14); // does not compile
return 0;
}
将 A 类更改为
class A
{
public:
A() = default;
~A() = default;
A(const A&) = delete;
A(A&&) = delete;
A& operator=(const A&) = delete;
A& operator=(A&&) = delete;
A& operator<<(const int i) &
{
std::cout << "operator<< called on lvalue" << std::endl;
return *this;
}
A&& operator<<(const int i) &&
{
std::cout << "operator<< called on rvalue" << std::endl;
return std::move(*this);
}
};
使程序编译。但是,使用 std::move 返回右值通常不是一个好主意,因为它会返回悬空引用或阻止编译器进行某些优化。
所描述的情况是经验法则“不按右值返回”的少数例外之一,还是应该以不同的方式解决问题?
万分感谢!
该代码完全有效且安全。因为你的对象已经是一个右值
A&& operator<<(const int i) &&
再次将其转换为右值(通过移动)不会改变代码的安全性。在这种情况下,不会发生 NRVO 优化,因此代码速度不太可能受到影响。
所以当你制定它时我会说“是的,这是规则的例外”
此外,这条规则并不通用:如果您了解正在发生的事情(这就是您问这个问题的原因),您可以依靠您的良好判断力而不是它。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)