【发布时间】:2019-11-28 10:29:06
【问题描述】:
如何在最后 3 个运算符中强制执行 RVO:
#include <iostream>
class Noisy {
private:
int m_value;
public:
Noisy(int value = 0): m_value(value)
{
std::cout << "Noisy(int)\n";
}
Noisy(const Noisy& other): m_value(other.m_value)
{
std::cout << "Noisy(const Noisy&)\n";
}
Noisy(Noisy&& other): m_value(other.m_value)
{
std::cout << "Noisy(Noisy&&)\n";
}
//~Noisy() {
// std::cout << "dtor\n";
//}
Noisy operator+(const Noisy& rhs) &
{
std::cout << "+(const Noisy&)&\n";
return Noisy(m_value + rhs.m_value);
}
Noisy operator+(Noisy&& rhs) &
{
std::cout << "+(Noisy&&)&\n";
rhs.m_value += m_value;
return rhs; //std::move(rhs);
}
Noisy operator+(const Noisy& rhs) &&
{
std::cout << "+(const Noisy&) &&\n";
this->m_value += rhs.m_value;
return *this; //std::move(*this);
}
Noisy operator+(Noisy&& rhs) &&
{
std::cout << "+(Noisy&&) &&\n";
this->m_value += rhs.m_value;
return *this; //std::move(*this);
}
};
int main()
{
Noisy a, b, c, d, e, f, g;
Noisy z = a + b + c + d + e + f + g;
return 0;
}
程序运行输出:
Noisy(int)
Noisy(int)
Noisy(int)
Noisy(int)
Noisy(int)
Noisy(int)
Noisy(int)
+(const Noisy&)&
Noisy(int)
+(const Noisy&) &&
Noisy(const Noisy&)
+(const Noisy&) &&
Noisy(const Noisy&)
+(const Noisy&) &&
Noisy(const Noisy&)
+(const Noisy&) &&
Noisy(const Noisy&)
+(const Noisy&) &&
Noisy(const Noisy&)
或者在最后三个运算符中显式使用std::move 时:
Noisy(int)
Noisy(int)
Noisy(int)
Noisy(int)
Noisy(int)
Noisy(int)
Noisy(int)
+(const Noisy&)&
Noisy(int)
+(const Noisy&) &&
Noisy(Noisy&&)
+(const Noisy&) &&
Noisy(Noisy&&)
+(const Noisy&) &&
Noisy(Noisy&&)
+(const Noisy&) &&
Noisy(Noisy&&)
+(const Noisy&) &&
Noisy(Noisy&&)
我不想在操作符中复制,像这样:
Noisy(int)
Noisy(int)
Noisy(int)
Noisy(int)
Noisy(int)
Noisy(int)
Noisy(int)
+(const Noisy&)&
Noisy(int)
+(const Noisy&) &&
+(const Noisy&) &&
+(const Noisy&) &&
+(const Noisy&) &&
+(const Noisy&) &&
到目前为止,我想到的唯一方法是从运算符返回引用,但这显然会导致引用悬空。
我用新鲜的 g++ 在 c++14 和 c++17 中编译。
更新
我知道在不违反规则的情况下强制编译器执行我想要的操作是不可能的。
但是编译器在本地优化右值的 ptevents 是什么?
我想它可以在第一次添加时创建一个右值,在下一次添加中修改它,然后分配给结果变量。
【问题讨论】:
-
您的最后 3 个运算符返回一个副本。你不能在这里做 RVO,因为那会修改
this。 -
@user207421
operator+应该返回一个新值。但它不应该修改操作数。所以这是错误的,但出于不同的原因。 -
@juanchopanza 如果存在可以修改和返回的右值引用,为什么它应该返回一个新值?
-
@AndreyGodyaev 这些是二进制
operator+的预期语义。你传递了两件事,你又得到了另一件事。修改任一操作数只会令人困惑。