gpt4 book ai didi

c++ - 如何对运算符返回值强制执行 RVO?

转载 作者:行者123 更新时间:2023-12-01 14:58:25 27 4
gpt4 key购买 nike

如何在最后 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&) &&

到目前为止,我认为的唯一方法是从运算符(operator)返回引用,但这显然会导致引用悬空。

我用新鲜的 g++ 在 c++14 和 c++17 中编译。

更新

我知道在不违反规则的情况下,不可能强制编译器做我想做的事。
但是编译器在本地优化右值的 ptevents 是什么?
我想它可以在第一次添加期间创建一个右值,该右值在下一次添加中被修改,然后分配给结果变量。

最佳答案

简短回答

让您的右值引用调用者 + const-reference 参数运算符返回一个右值引用,即 std::move编辑于 *this .

Noisy&& operator+(const Noisy& rhs) &&
{
std::cout << "+(const Noisy&)&&\n";
m_value += rhs.m_value;
return std::move(*this);
}

由于这是从右值引用触发的,因此您可以随意滥用和移动 *this到调用者,他们可以自由地做任何他们想做的事情。

示例
#include <iostream>

class Noisy {
private:
int m_value;
public:
Noisy(int value = 0) : m_value(value)
{
std::cout << "Noisy()\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";
other.m_value = -1;
}

~Noisy()
{
std::cout << "~Noisy() : " << m_value << '\n';
}

Noisy operator+(const Noisy& rhs) const &
{
std::cout << "+(const Noisy&)&\n";
return Noisy(m_value + rhs.m_value);
}

Noisy&& operator+(const Noisy& rhs) &&
{
std::cout << "+(const Noisy&)&&\n";
m_value += rhs.m_value;
return std::move(*this);
}

Noisy operator+(Noisy&& rhs) const
{
std::cout << "+(Noisy&&)\n";
rhs.m_value += m_value;
return std::move(rhs);
}
};

int main()
{
Noisy a, b, c, d, e, f, g;
std::cout << "========================\n";

Noisy z = a + b + c + d + e + f + g;
std::cout << "========================\n";

return 0;
}

输出

Noisy()
Noisy()
Noisy()
Noisy()
Noisy()
Noisy()
Noisy()
========================
+(const Noisy&)&
Noisy()
+(const Noisy&)&&
+(const Noisy&)&&
+(const Noisy&)&&
+(const Noisy&)&&
+(const Noisy&)&&
Noisy(Noisy&&)
~Noisy() : -1
========================
~Noisy() : 0
~Noisy() : 0
~Noisy() : 0
~Noisy() : 0
~Noisy() : 0
~Noisy() : 0
~Noisy() : 0
~Noisy() : 0
a.operator+(b)初步 build 后的通知,结果对象通过右值引用沿链传播。最后一个操作是移动构造到 z . (因此,析构函数报告中的 -1)。

我已经准备了一个关于您的运算符(operator)链接如何使我要发布的工作的长篇描述,但最后它变得相当困惑。可以这么说:
Noisy z = a.operator+(b).operator+(c).operator+(....

是你在做什么,你需要得到所有过去的 lhs 操作数 (b)在链中将其右值引用推送到下一个调用。我展示的运算符(operator)将允许这样做。

祝你好运,我希望我能理解你的目标。

关于c++ - 如何对运算符返回值强制执行 RVO?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59086700/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com