gpt4 book ai didi

c++ - 重载算术中的 move 语义和传递右值引用

转载 作者:IT老高 更新时间:2023-10-28 23:15:43 26 4
gpt4 key购买 nike

我正在用 C++ 编写一个小型数值分析库。我一直在尝试使用包括 move 语义在内的最新 C++11 特性来实现。我理解以下帖子中的讨论和最佳答案:C++11 rvalues and move semantics confusion (return statement) ,但有一种情况我仍在尝试解决。

我有一个类,叫它T,它完全配备了重载运算符。我也有复制和 move 构造函数。

T (const T &) { /*initialization via copy*/; }
T (T &&) { /*initialization via move*/; }

我的客户端代码大量使用运算符,因此我试图确保复杂的算术表达式从 move 语义中获得最大 yield 。考虑以下几点:

T a, b, c, d, e;
T f = a + b * c - d / e;

在没有 move 语义的情况下,我的运算符(operator)每次都使用复制构造函数创建一个新的局部变量,所以总共有 4 个拷贝。我希望通过 move 语义我可以将其减少到 2 个拷贝加上一些 move 。在括号内的版本中:

T f = a + (b * c) - (d / e);

(b * c)(d/e) 中的每一个都必须以通常的方式使用拷贝创建临时文件,但是如果我可以利用其中一个临时工来累积剩余的结果。

使用 g++ 编译器,我已经能够做到这一点,但我怀疑我的技术可能不安全,我想完全了解原因。

这是加法运算符的示例实现:

T operator+ (T const& x) const
{
T result(*this);
// logic to perform addition here using result as the target
return std::move(result);
}
T operator+ (T&& x) const
{
// logic to perform addition here using x as the target
return std::move(x);
}

如果不调用 std::move,则只会调用每个运算符的 const & 版本。但是当如上所述使用 std::move 时,随后的算术(在最里面的表达式之后)是使用每个运算符的 && 版本执行的。

我知道 RVO 可以被抑制,但在计算量非常大的实际问题上,似乎 yield 略高于缺乏 RVO。也就是说,当我包含 std::move 时,经过数百万次计算,我确实得到了非常小的加速。虽然老实说,没有它就足够快了。我真的只是想完全理解这里的语义。

是否有好心的 C++ 大师愿意花时间以简单的方式解释我在这里使用 std::move 是否以及为什么是一件坏事?非常感谢。

最佳答案

您应该更喜欢将运算符重载为自由函数以获得完整的类型对称性(可以在左侧和右侧应用相同的转换)。这使得问题中遗漏的内容更加明显。重申您的运营商作为您提供的免费功能:

T operator+( T const &, T const & );
T operator+( T const &, T&& );

但您未能提供将左侧作为临时处理的版本:

T operator+( T&&, T const& );

当两个参数都是右值时,为了避免代码中的歧义,您需要提供另一个重载:

T operator+( T&&, T&& );

常见的建议是将 += 实现为修改当前对象的成员方法,然后将 operator+ 编写为修改当前对象的转发器界面。

我并没有真正考虑这么多,但可能有使用 T 的替代方法(没有 r/lvalue 引用),但我担心它不会减少您需要提供的重载数量使 operator+ 在所有情况下都高效。

关于c++ - 重载算术中的 move 语义和传递右值引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13166079/

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