【发布时间】:2014-01-02 17:55:21
【问题描述】:
我正在用一个简单的Vector 类试验rvalue 引用,试图消除二进制操作中不需要的临时对象。经过一番挣扎,我发现operator+()有以下两个重载:
// overload called if right = lvalue and left = lvalue/rvalue
friend Vector<T> operator+(Vector<T> a, const Vector<T>& b) {
a += b;
return a;
}
// overload called if right = rvalue and left = lvalue/rvalue
friend Vector<T> operator+(const Vector<T>& a, Vector<T>&& b) {
b += a;
return std::move(b);
}
我可以确保在像auto x = a+b+c+d+...; 这样的表达式中,只要至少a 或b 是临时的,将调用移动构造函数而不创建任何新的临时变量。
另一方面,即使a 和b(比如d)之后的值之一是lvalue,从技术上讲,这应该足以避免复制。编译器是否可以通过扫描给定表达式以找到至少一个临时表达式并根据该值开始调用 operator+ 来进行任何优化?
示例 1:
#include "vector.h"
Vector<double> get() {
return {0, 1, 2, 6};
}
int main (){
auto a = get();
auto b = get();
auto c = a + get() + b;
std::cout << c << std::endl;
return 0;
}
输出:
calling move ctor
calling move ctor
[0, 3, 6, 18]
示例 2:
#include "vector.h"
Vector<double> get() {
return {0, 1, 2, 6};
}
int main (){
auto a = get();
auto b = get();
auto c = a + b + get();
std::cout << c << std::endl;
return 0;
}
输出:
calling copy ctor
calling move ctor
[0, 3, 6, 18]
【问题讨论】:
-
可以用
sum(a,b,get() )代替operator+(a, operator+(b, get() ) )吗?这样你就有了表达式每个部分的 lvale/rvalue 信息,但是一旦你开始处理任意表达式,它就会变得丑陋(我正在考虑构建一个表达式树,就像在 eigen.tuxfamily.org/dox/TopicInsideEigenExample.html 中一样)。
标签: c++ optimization c++11 move-semantics rvalue-reference