Skip to content

Latest commit

 

History

History
124 lines (85 loc) · 3.28 KB

perfect-forwarding.rst

File metadata and controls

124 lines (85 loc) · 3.28 KB

Perfect Forwarding

Perfect Forwarding 指的是函式可以原封不動 (保持原 lvalue/rvalue 性質)地把資料傳給真正要建立的地方, 藉此可以省去中間傳遞時不必要的複製。

std::forward 是一個 conditional cast, 如果傳入的參數原本是 rvalue 的話, 才會進行轉換, 把它轉成 rvalue。

相對的 std::move 是無論如何都會把傳入的參數轉成 rvalue。

template<class T>
void wrapper(T&& arg)   // universal reference
{
    // arg is always lvalue
    foo(std::forward<T>(arg)); // Forward as lvalue or as rvalue, depending on T
}

在 C++11 之後 STL 內的資料結構都多了 emplace 相關的函式可以呼叫, 以 vector 為例:

  • push_back(mystring) :copy
  • push_back(std::move(mystring)) :move
  • emplace_back(mystring) :copy,等同於 push_back(mystring)
  • emplace_back(std::move(mystring)) :move,等同於 push_back(std::move(mystring))
  • emplace_back("mydata") :in-place construction

使用 emplace 版本的結果可能會等同於原本的版本, 但在直接傳入內部資料時, emplace 版本就會比較有效率。

template<typename... Args>
void stepper::rturn(Args&&... args) const
{
    turn(std::forward<Args>(args)..., true);
}
  • 對 rvalue reference 使用 std::move
    • Widget&& 是 rvalue reference
    • vector<T>&& 是 rvalue reference
  • 對 universal reference 使用 std::forward
    • T&& 是 universal reference
    • auto&& 是 universal reference
  • 如果是會被 RVO/NRVO 優化掉的 local 物件,不要套用 std::move 或 std::forward

rvalue reference:

class Widget {
public:
    Widget(Widget&& rhs)    // rhs is rvalue reference
    : name(std::move(rhs.name)),
      p(std::move(rhs.p))
    { ... }
    ...

private:
    std::string name;
    std::shared_ptr<SomeDataStructure> p;
};

universal reference:

class Widget {
public:
    template<typename T>
    void setName(T&& newName)   // universal reference
    { name = std::forward<T>(newName); }
    ...
};