2017-02-20 46 views
1

我想写我的vec类。为了提高效率,我使用移动语义。在C++中,是否有任何方法来减少具有移动语义的成员函数的数量?

Vec<int> v1; 
Vec<int> v2; 
Vec<int> v3; 
Vec<int> v4; 
v4 = v1 + v2;     // Line 1 
v4 = v1 + v2 + v3;    // Line 2 
v4 = v1 + (v2 + v3);   // Line 3 

但是,为了让上面的每一行只调用一次拷贝构造函数,我必须用一个操作符重载四个函数。像下面的代码一样。

Vec(Myself&& v) 
{ // move consturctor 
    dim = v.dim; 
    value = std::move(v.value); 
} 

Myself& operator+= (const Myself& v) 
{ 
    for (size_type i = 0; i < dim; ++i) (*this)[i] += v[i]; 
    return *this; 
} 

template<typename std::enable_if<!std::is_reference<Myself>::value>::type* = nullptr> // SFINAE 
friend Myself& operator+ (Myself&& a, const Myself& b) 
{ 
    return a += b; 
} 

Myself& operator+ (Myself&& v) const 
{ 
    return v += *this; 
} 

Myself operator+ (const Myself& v) const 
{ 
    Myself ansV(*this); 
    ansV += v; 
    return ansV; 
} 

感谢亮度种族在轨道的提醒。我将移动构造函数添加到上面的代码中。

1.有什么办法可以为一个操作符编写较少的函数吗?

2.为什么在功能friend Myself& operator+ (Myself&& a, const Myself& b)上添加了SFINAE,而不是Myself& operator+ (Myself&& v) const?它用于修复v4 = v1 + (v2 + v3);的混淆。

+0

在哪里你的动作?我没有看到任何。 –

+0

每个问题请提出一个问题。 –

+2

'return v + = * this;'这不是倒退? –

回答

2

当我写运营商算术类T,我通常会做到以下几点:

(一)如果操作是可交换的(A + B等于B + A):

认沽的+=执行到T:

T & T::operator+=(T const& other) { 
    // [Perform the actual operation (add other to *this)] 
    x += other.x; // or something similar 
    return *this; 
} 

提供以下两个函数的类的外部:

T operator+(T a, T const& b) { 
    a += b; 
    return a; 
} 

T operator+(T const& a, T && b) { 
    MyInt temp(std::move(b)); 
    temp += a; 
    return temp; 
} 

(b)如果操作是不可交换的(AB是选自Ba不同):

放的-=实施成T和提供在所述第二操作数的工作原理的替代的第二功能第一:

T & T::operator-=(T const& other) { 
    // [Perform the actual operation of (subtract other from *this)] 
    x -= other.x; // or something similar 
    return *this; 
} 

void T::operatorMinus(T & other) const { 
    // [Perform the actual operation, but work on other instead of *this] 
    other.x = x - other.x; // or something similar 
} 

提供类的外部以下两种功能:

T operator-(T a, T const& b) { 
    a -= b; 
    return a; 
} 

T operator-(T const& a, T && b) { 
    MyInt temp(std::move(b)); 
    a.operatorMinus(temp); 
    return temp; 
} 

结果:

GCC和铛现在只需要在以下实施例中使用-O3单个拷贝构造(同样为operator-):

T a1, a2, a3, x; 
x = a1 + a2; 
x = a1 + a2 + a3; 
x = (a1 + a2) + a3; 
x = a1 + (a2 + a3); 

即使在两个操作数都是右值的处理的情况下没有歧义。下面编译罚款,即使需要两个副本(a1+a2一个副本和一个副本a3+a4):

T a1, a2, a3, a4, x; 
x = (a1 + a2) + (a3 + a4); 
+1

在你的动作中,你可以颠倒'a'和'b'的顺序:'temp + = a;'。如果依赖于'a'和'b'的顺序,你将如何实现它?因此'a + b!= b + a'?编辑:这已经是'operator -'的情况.... – JHBonarius

+0

@JHBonarius如果操作不可交换,则需要至少提供两个实现:像以前一样,“default”实现和实现保持第一个操作数不变并在第二个操作数上运行。在'operator-'的情况下,你可以使用类似'a-b = - (b-a)'的东西,但是通常情况下(例如矩阵乘法),这不是微不足道的。 – pschill

+1

@ J.H.Bonarius我更新了我的答案并包含了非交换的情况。 – pschill

相关问题