2011-12-31 80 views
1

如何用operator+實現移動語義的正確方法?類似於std::string的工作方式?運算符+和移動語義

我曾嘗試以下,但我希望有一些更優雅,更可能是正確的方式做到這一點:

class path 
{ 
    std::vector<std::string> path_; 
public: 

    path& path::operator+=(const path& other) 
    { 
     path_.insert(std::begin(path_), std::begin(other.path_), std::end(other.path_)); 
     return *this; 
    } 

    path& path::operator+=(path&& other) 
    { 
     path_.insert(std::begin(path_), std::make_move_iterator(std::begin(other.path_)), std::make_move_iterator(std::end(other.path_))); 
     return *this; 
    } 
}; 

template<typename L, typename R> 
typename std::enable_if<std::is_convertible<path, L>::value, path>::type operator+(const L& lhs, const R& rhs) 
{ 
    auto tmp = std::forward<L>(lhs); 
    tmp  += std::forward<R>(rhs); 
    return tmp; 
} 

回答

2

太複雜。 :)只要通過你應該已經遵循了規則遵守:

  • operator+的LHS的值
  • 在LHS

實施的operator+=方面operator+這已經是真正的C++ 03,因爲複製elision和RVO。經驗法則:如果您複製副本,請在參數中進行設置。

考慮到這一點:

#include <iterator> 
#include <utility> 

class path 
{ 
    std::vector<std::string> path_; 
public: 

    path& operator+=(path other) 
    { 
     auto op_begin = std::make_move_iterator(std::begin(other.path_)); 
     auto op_end = std::make_move_iterator(std::end(other.path_)); 
     path_.reserve(path_.size() + other.path_.size()); 
     path_.insert(std::end(path_), op_begin, op_end); 
     return *this; 
    } 
}; 

path operator+(path lhs, path rhs) 
{ 
    return std::move(lhs += std::move(rhs)); 
} 

這應該是最理想的方式。請注意,我也將operator+=更改爲追加的路徑,而不是預先計算(我希望這是您的想法,如果不是,請隨時將其更改爲std::begin(path_))。

我也做了operator+operator+=的值,然後只是移動它們。 std::make_move_iterator也是一個不錯的工具。顧名思義,不是複製,而是移動指向的元素。這應該真的像它將要獲得的那樣快。

另一個版本可能是operator+=使用的std::move迭代版本:

path& operator+=(path other) 
{ 
    path_.reserve(path_.size() + other.path_.size()); 
    std::move(other.begin(), other.end(), std::back_inserter(path_)); 
    return *this; 
} 
+0

這顯然不是最優的形式。如果LHS是一個左值,那麼您只是冗餘地複製它。 – Puppy 2011-12-31 11:30:08

+1

@DeadMG:Ehm ..'operator +'無論如何都會返回一個新副本。我沒有看到多餘的副本在哪裏? – Xeo 2011-12-31 11:35:42

+0

lhs或rhs是否是一個xvalue並且可以重新使用? (只是一個想法) – Kos 2011-12-31 11:58:36