我正在使用C++编写一个小型的数值分析库。 我一直在尝试使用最新的C++11功能,包括移动语义来实现。 我理解了以下帖子中的讨论和最佳答案:C++11 rvalues and move semantics confusion (return statement),但仍有一种情况我还在努力理解。
我有一个类,叫做T
,它完全装备了重载运算符,同时具有复制和移动构造函数。
T (const T &) { /*initialization via copy*/; }
T (T &&) { /*initialization via move*/; }
我的客户端代码大量使用操作符,因此我正在尝试确保复杂的算术表达式从移动语义中获得最大的好处。考虑以下情况:
T a, b, c, d, e;
T f = a + b * c - d / e;
没有移动语义,每次我的运算符都会使用复制构造函数创建一个新的本地变量,因此总共有4个副本。我希望使用移动语义可以将此减少到2个副本加上一些移动操作。在括号版本中:
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,但在非常计算密集型的真实问题中,似乎获益略微超过了缺乏RVO。也就是说,在数百万次计算中,当我包括std::move
时,我确实获得了非常微小的加速。尽管如此,它已经足够快了。我真的只想完全理解这里的语义。
是否有一位友善的C++大师愿意花时间简单地解释一下,我的使用std::move
是否合适以及原因?非常感谢。
T
是什么类型的数字类型?它是否通过指针在堆上管理某些内容?因为如果它只有一些int
成员之类的东西,移动语义将不会带来任何好处。只是问一下 :) - fredoverflow