2017-02-20 40 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

相關問題