右辺値リンクの簡単な紹介

Rvalue References、Howard E. Hinnant、Bjarne Stroustrup、Bronek Kozickiの簡単な紹介の翻訳。

右辺値参照は、C ++言語の小さな技術的拡張です。 プログラマーは、論理的に不必要なコピーを避け、完全な転送機能を提供できます。 まず第一に、それらは高性能プロジェクトとライブラリでの使用を目的としています。

はじめに


このドキュメントは、新しいC ++言語関数-右辺値参照の初期概念を示します。 これは短いチュートリアルであり、完全な記事ではありません。 詳細については、最後にあるリンクのリストを参照してください。

右辺値リンク


右辺値参照は複合型で、C ++の従来の参照に非常に似ています。 これら2つのタイプを区別するために、従来のC ++リンクを左辺値リンクと呼びます。 リンクという用語が表示される場合、これは両方のタイプのリンク、左辺値リンク、右辺値リンクに適用されます。

左辺値のセマンティクスによれば、リンクは特定のタイプの後に&を置くことによって形成されます。

A a; A& a_ref1 = a; //  lvalue  

何らかのタイプの後に&&を入力すると、右辺値リンクが取得されます。

 A a; A&& a_ref2 = a; //  rvalue  

右辺値参照は左辺値参照とまったく同じように動作しますが、左辺値は一時(非定数)オブジェクトに関連付けることはできませんが、一時オブジェクトに関連付けることができます。

 A& a_ref3 = A(); // ! A&& a_ref4 = A(); // Ok 

質問:なぜこれが必要なのでしょうか?!

右辺値リンクと左辺値リンクの組み合わせは、移動セマンティクスを簡単に実装するために必要なものであることがわかります。 右辺値リンクを使用して完全な転送を実現することもできますが、これは以前はC ++で未解決の問題でした。 ほとんどのプログラマにとって、右辺値リンクを使用すると、より生産的なライブラリを作成できます。

動作のセマンティクス(動作セマンティクス)


サイドコピーの除去

コピーは高価な喜びです。 たとえば、2つのベクトルの場合、 v2 = v1と記述すると、通常、これにより関数呼び出し、メモリ割り当て、およびループが発生します。 もちろん、これはベクターの2つのコピーが本当に必要な場合には受け入れられますが、多くの場合、そうではありません。ベクターをある場所から別の場所にコピーし、古いコピーを削除することがよくあります。 考慮してください:

 template <class T> swap(T& a, T& b) { T tmp(a); //       a a = b; //        b b = tmp; //        tmp (.. a) } 

実際、 aまたはbコピーは必要ありません。それらを交換したいだけです。 もう一度試してみましょう。

 template <class T> swap(T& a, T& b) { T tmp(std::move(a)); a = std::move(b); b = std::move(tmp); } 

このmove()呼び出しは、パラメーターとして渡されたオブジェクトの値を返しますが、このオブジェクトの安全性を保証するものではありません。 たとえば、 move()パラメーターとしてvectorを渡すと、関数が実行された後、すべての要素がコピーされずに移動されるため、パラメーターの長さがゼロのベクトルが残ることが合理的に期待できます。 つまり、動きは破壊的な読み取りです。

この場合、特殊化swapを最適化しました。 ただし、大きなオブジェクトを削除または上書きする直前にコピーするすべての関数を特殊化することはできません。 それは非建設的です。

右辺値リンクの主なタスクは、コードまたはランタイムのオーバーヘッドを書き換えずに再配置を実装できるようにすることです。

移動する

move機能は実際には非常に控えめな仕事をします。 彼女の仕事は、左辺値または右辺値パラメーターのいずれかを受け入れ、コピーコンストラクターを呼び出さずに右辺値として返すことです。

 template <class T> typename remove_reference<T>::type&& move(T&& a) { return a; } 

現在、すべてがクライアントコードに依存しています。クライアントコードでは、キー関数(たとえば、コピーコンストラクターや代入演算子)がオーバーロードされ、パラメーターが左辺値か右辺値かが決まります。 パラメーターが左辺値の場合、コピーが必要です。 右辺値の場合、移動を安全に実行できます。

左辺値/右辺値のオーバーロード

リソースを所有し、コピーセマンティクス(コピーコンストラクターと代入演算子)も提供する単純なクラスを考えます。 たとえば、 clone_ptrはポインターを所有し、その上で高価なclone()メソッドを呼び出してコピーします。

 template <class T> class clone_ptr { private: T* ptr; public: //  explicit clone_ptr(T* p = 0) : ptr(p) {} //  ~clone_ptr() {delete ptr;} //   clone_ptr(const clone_ptr& p) : ptr(p.ptr ? p.ptr->clone() : 0) {} clone_ptr& operator=(const clone_ptr& p) { if (this != &p) { delete ptr; ptr = p.ptr ? p.ptr->clone() : 0; } return *this; } //   clone_ptr(clone_ptr&& p) : ptr(p.ptr) {p.ptr = 0;} clone_ptr& operator=(clone_ptr&& p) { std::swap(ptr, p.ptr); return *this; } //   T& operator*() const {return *ptr;} // ... }; 

移動のセマンティクスを除き、 clone_ptrは、今日のC ++ブックにあるコードです。 ユーザーはclone_ptrようにclone_ptr使用できます。

 clone_ptr<base> p1(new derived); // ... clone_ptr<base> p2 = p1; //  p2  p1      


clone_ptrコピーコンストラクターまたは代入演算子のclone_ptrは、比較的高価な操作であることに注意してください。 ただし、コピー元が右辺値の場合、右辺値ポインタを盗むことで、潜在的に高価なclone()操作の呼び出しを回避できます(誰も気付かないでしょう!)。 移動セマンティクスでは、移動コンストラクターは作成されたオブジェクトに右辺値を残し、割り当て演算子は現在のオブジェクトの値をリンクの右辺値オブジェクトと交換します。

これで、コードが右辺値clone_ptrをコピーしようとしたとき、または右辺値コピーのソースを読み取る明示的な許可がある場合( std::moveを使用)、作業ははるかに高速になります。

 clone_ptr<base> p1(new derived); // ... clone_ptr<base> p2 = std::move(p1); //  p2  ,  p1 

他のクラスで構成されるクラスの場合(包含または継承のいずれか)、ムーブコンストラクターとムーブの割り当ては、 std::move関数を使用して簡単に実装できます。

 class Derived : public Base { std::vector<int> vec; std::string name; // ... public: // ... //   Derived(Derived&& x) //   rvalue : Base(std::move(x)), vec(std::move(x.vec)), name(std::move(x.name)) { } Derived& operator=(Derived&& x) //   rvalue { Base::operator=(std::move(x)); vec = std::move(x.vec); name = std::move(x.name); return *this; } // ... }; 

これで、各サブオブジェクトは、オブジェクトの移動コンストラクターおよび移動割り当て演算子で右辺値として扱われます。 std::vectorおよびstd::string場合、移動操作は既に実装されており( clone_ptr )、より高価なコピー操作を回避できます。

パラメータx 、右辺値参照として宣言されているという事実にもかかわらず、再配置操作では左辺値として扱われることに注意してください。 したがって、基本クラスに渡すときは、 xだけでなくmove(x)使用move(x)必要があります。 これは、名前付き変数から誤って二重に移動しようとするのを防ぐように設計された、移動セマンティクスの重要なセキュリティメカニズムです。 すべての移動は、右辺値からのみ、または右辺値への明示的なキャスト( std::moveを使用)でのみ発生します。 変数に名前がある場合、これは左辺値です。

質問:リソースを所有しないタイプについてはどうですか? (たとえば、 std::complex ?)

この場合、作業は必要ありません。 コピーコンストラクタは、右辺値を使用したコピーにすでに最適です。

移動可能だがコピーできないタイプ


一部のタイプのコピーセマンティクスは適用されませんが、移動できます。 例:


そのようなタイプを移動可能にすると(コピーされないまま)、それらのユーザビリティは非常に向上します。 移動可能であるがコピーされていないオブジェクトは、ファクトリメソッド(パターン)の値によって返されます。

 ifstream find_and_open_data_file(/* ... */); ... ifstream data_file = find_and_open_data_file(/* ... */); //  ! 

この例では、ベースファイル記述子が1つのオブジェクトから別のオブジェクトに転送されます。 ifstreamソースは右辺値です。 どの時点でも、ファイル記述子は1つだけで、 ifstream所有するのは1つだけです。

再配置可能だがコピーされていない型は、標準のコンテナに配置することもできます。 コンテナがそれ自体の内部で要素を「コピー」する必要がある場合(たとえばvector実装する場合)、コピーする代わりに単純に移動します。

 vector<unique_ptr<base>> v1, v2; v1.push_back(unique_ptr<base>(new derived())); // OK,    ... v2 = v1; //   !    . v2 = move(v1); //  .     v2. 

多くの標準アルゴリズムは、シーケンスの要素をコピーする代わりに移動することで恩恵を受けます。 これにより、パフォーマンスが向上するだけでなく( std::swapの実装の場合は上記で説明しています)、これらのアルゴリズムがコピー不可(ただし移動可能)なタイプでも機能するようになります。 たとえば、次のコードは並べ替えます
 vector<unique_ptr>,   ,     : 

struct indirect_less { template <class T> bool operator()(const T& x, const T& y) {return *x < *y;} }; ... std::vector<std::unique_ptr<A>> v; ... std::sort(v.begin(), v.end(), indirect_less());

unique_ptr , swap ( , ) / . , , . ( , ), .

(perfect forwarding)
, std::shared_ptr . . , , . :

template <class T> std::shared_ptr<T> factory() // { return std::shared_ptr<T>(new T); } template <class T, class A1> std::shared_ptr<T> factory(const A1& a1) // { return std::shared_ptr<T>(new T(a1)); } //
. :

std::shared_ptr<A> p = factory<A>(5);
: , T ?

, factory T .

factory :

template <class T, class A1> std::shared_ptr<T> factory(A1& a1) { return std::shared_ptr<T>(new T(a1)); }
. const factory , (, A1 ) T . , , T . (, std::bind ).

:

std::shared_ptr<A> p = factory<A>(5); // ! A* q = new A(5); // OK
factory , "5" factory , int& rvalue "5". , , .

: AI & const AI &?

, : 4 . 8 . 16 .. .

Rvalue :

template <class T, class A1> std::shared_ptr<T> factory(A1&& a1) { return std::shared_ptr<T>(new T(std::forward<A1>(a1))); }
rvalue factory . const , factory .

: forward ?

move , forward - , , , . a1 , .

, forward lvalue/rvalue , factory . factory rvalue, forward T rvalue. , lvalue factory , T lvalue.

forward :

template <class T> struct identity { typedef T type; }; template <class T> T&& forward(typename identity<T>::type&& a) { return a; }

, . , 95% .

, , , , N1377 .

N1385 .

rvalue ( ), N1690 .

, rvalue , N1952 .

rvalue , N2027 .

rvalue , N1771 .

, rvalue , :
N1856 N1857 N1858 N1859 N1860 N1861 N1862
rvalue (this), N1821 .
vector<unique_ptr>, , :

struct indirect_less { template <class T> bool operator()(const T& x, const T& y) {return *x < *y;} }; ... std::vector<std::unique_ptr<A>> v; ... std::sort(v.begin(), v.end(), indirect_less());

unique_ptr , swap ( , ) / . , , . ( , ), .

(perfect forwarding)
, std::shared_ptr . . , , . :

template <class T> std::shared_ptr<T> factory() // { return std::shared_ptr<T>(new T); } template <class T, class A1> std::shared_ptr<T> factory(const A1& a1) // { return std::shared_ptr<T>(new T(a1)); } //
. :

std::shared_ptr<A> p = factory<A>(5);
: , T ?

, factory T .

factory :

template <class T, class A1> std::shared_ptr<T> factory(A1& a1) { return std::shared_ptr<T>(new T(a1)); }
. const factory , (, A1 ) T . , , T . (, std::bind ).

:

std::shared_ptr<A> p = factory<A>(5); // ! A* q = new A(5); // OK
factory , "5" factory , int& rvalue "5". , , .

: AI & const AI &?

, : 4 . 8 . 16 .. .

Rvalue :

template <class T, class A1> std::shared_ptr<T> factory(A1&& a1) { return std::shared_ptr<T>(new T(std::forward<A1>(a1))); }
rvalue factory . const , factory .

: forward ?

move , forward - , , , . a1 , .

, forward lvalue/rvalue , factory . factory rvalue, forward T rvalue. , lvalue factory , T lvalue.

forward :

template <class T> struct identity { typedef T type; }; template <class T> T&& forward(typename identity<T>::type&& a) { return a; }

, . , 95% .

, , , , N1377 .

N1385 .

rvalue ( ), N1690 .

, rvalue , N1952 .

rvalue , N2027 .

rvalue , N1771 .

, rvalue , :
N1856 N1857 N1858 N1859 N1860 N1861 N1862
rvalue (this), N1821 .

vector<unique_ptr>, , :

struct indirect_less { template <class T> bool operator()(const T& x, const T& y) {return *x < *y;} }; ... std::vector<std::unique_ptr<A>> v; ... std::sort(v.begin(), v.end(), indirect_less());

unique_ptr , swap ( , ) / . , , . ( , ), .

(perfect forwarding)
, std::shared_ptr . . , , . :

template <class T> std::shared_ptr<T> factory() // { return std::shared_ptr<T>(new T); } template <class T, class A1> std::shared_ptr<T> factory(const A1& a1) // { return std::shared_ptr<T>(new T(a1)); } //
. :

std::shared_ptr<A> p = factory<A>(5);
: , T ?

, factory T .

factory :

template <class T, class A1> std::shared_ptr<T> factory(A1& a1) { return std::shared_ptr<T>(new T(a1)); }
. const factory , (, A1 ) T . , , T . (, std::bind ).

:

std::shared_ptr<A> p = factory<A>(5); // ! A* q = new A(5); // OK
factory , "5" factory , int& rvalue "5". , , .

: AI & const AI &?

, : 4 . 8 . 16 .. .

Rvalue :

template <class T, class A1> std::shared_ptr<T> factory(A1&& a1) { return std::shared_ptr<T>(new T(std::forward<A1>(a1))); }
rvalue factory . const , factory .

: forward ?

move , forward - , , , . a1 , .

, forward lvalue/rvalue , factory . factory rvalue, forward T rvalue. , lvalue factory , T lvalue.

forward :

template <class T> struct identity { typedef T type; }; template <class T> T&& forward(typename identity<T>::type&& a) { return a; }

, . , 95% .

, , , , N1377 .

N1385 .

rvalue ( ), N1690 .

, rvalue , N1952 .

rvalue , N2027 .

rvalue , N1771 .

, rvalue , :
N1856 N1857 N1858 N1859 N1860 N1861 N1862
rvalue (this), N1821 .

vector<unique_ptr>, , :

struct indirect_less { template <class T> bool operator()(const T& x, const T& y) {return *x < *y;} }; ... std::vector<std::unique_ptr<A>> v; ... std::sort(v.begin(), v.end(), indirect_less());

unique_ptr , swap ( , ) / . , , . ( , ), .

(perfect forwarding)
, std::shared_ptr . . , , . :

template <class T> std::shared_ptr<T> factory() // { return std::shared_ptr<T>(new T); } template <class T, class A1> std::shared_ptr<T> factory(const A1& a1) // { return std::shared_ptr<T>(new T(a1)); } //
. :

std::shared_ptr<A> p = factory<A>(5);
: , T ?

, factory T .

factory :

template <class T, class A1> std::shared_ptr<T> factory(A1& a1) { return std::shared_ptr<T>(new T(a1)); }
. const factory , (, A1 ) T . , , T . (, std::bind ).

:

std::shared_ptr<A> p = factory<A>(5); // ! A* q = new A(5); // OK
factory , "5" factory , int& rvalue "5". , , .

: AI & const AI &?

, : 4 . 8 . 16 .. .

Rvalue :

template <class T, class A1> std::shared_ptr<T> factory(A1&& a1) { return std::shared_ptr<T>(new T(std::forward<A1>(a1))); }
rvalue factory . const , factory .

: forward ?

move , forward - , , , . a1 , .

, forward lvalue/rvalue , factory . factory rvalue, forward T rvalue. , lvalue factory , T lvalue.

forward :

template <class T> struct identity { typedef T type; }; template <class T> T&& forward(typename identity<T>::type&& a) { return a; }

, . , 95% .

, , , , N1377 .

N1385 .

rvalue ( ), N1690 .

, rvalue , N1952 .

rvalue , N2027 .

rvalue , N1771 .

, rvalue , :
N1856 N1857 N1858 N1859 N1860 N1861 N1862
rvalue (this), N1821 .
 vector<unique_ptr>,   ,     : 

struct indirect_less { template <class T> bool operator()(const T& x, const T& y) {return *x < *y;} }; ... std::vector<std::unique_ptr<A>> v; ... std::sort(v.begin(), v.end(), indirect_less());

unique_ptr , swap ( , ) / . , , . ( , ), .

(perfect forwarding)
, std::shared_ptr . . , , . :

template <class T> std::shared_ptr<T> factory() // { return std::shared_ptr<T>(new T); } template <class T, class A1> std::shared_ptr<T> factory(const A1& a1) // { return std::shared_ptr<T>(new T(a1)); } //
. :

std::shared_ptr<A> p = factory<A>(5);
: , T ?

, factory T .

factory :

template <class T, class A1> std::shared_ptr<T> factory(A1& a1) { return std::shared_ptr<T>(new T(a1)); }
. const factory , (, A1 ) T . , , T . (, std::bind ).

:

std::shared_ptr<A> p = factory<A>(5); // ! A* q = new A(5); // OK
factory , "5" factory , int& rvalue "5". , , .

: AI & const AI &?

, : 4 . 8 . 16 .. .

Rvalue :

template <class T, class A1> std::shared_ptr<T> factory(A1&& a1) { return std::shared_ptr<T>(new T(std::forward<A1>(a1))); }
rvalue factory . const , factory .

: forward ?

move , forward - , , , . a1 , .

, forward lvalue/rvalue , factory . factory rvalue, forward T rvalue. , lvalue factory , T lvalue.

forward :

template <class T> struct identity { typedef T type; }; template <class T> T&& forward(typename identity<T>::type&& a) { return a; }

, . , 95% .

, , , , N1377 .

N1385 .

rvalue ( ), N1690 .

, rvalue , N1952 .

rvalue , N2027 .

rvalue , N1771 .

, rvalue , :
N1856 N1857 N1858 N1859 N1860 N1861 N1862
rvalue (this), N1821 .
vector<unique_ptr>, , :

struct indirect_less { template <class T> bool operator()(const T& x, const T& y) {return *x < *y;} }; ... std::vector<std::unique_ptr<A>> v; ... std::sort(v.begin(), v.end(), indirect_less());

unique_ptr , swap ( , ) / . , , . ( , ), .

(perfect forwarding)
, std::shared_ptr . . , , . :

template <class T> std::shared_ptr<T> factory() // { return std::shared_ptr<T>(new T); } template <class T, class A1> std::shared_ptr<T> factory(const A1& a1) // { return std::shared_ptr<T>(new T(a1)); } //
. :

std::shared_ptr<A> p = factory<A>(5);
: , T ?

, factory T .

factory :

template <class T, class A1> std::shared_ptr<T> factory(A1& a1) { return std::shared_ptr<T>(new T(a1)); }
. const factory , (, A1 ) T . , , T . (, std::bind ).

:

std::shared_ptr<A> p = factory<A>(5); // ! A* q = new A(5); // OK
factory , "5" factory , int& rvalue "5". , , .

: AI & const AI &?

, : 4 . 8 . 16 .. .

Rvalue :

template <class T, class A1> std::shared_ptr<T> factory(A1&& a1) { return std::shared_ptr<T>(new T(std::forward<A1>(a1))); }
rvalue factory . const , factory .

: forward ?

move , forward - , , , . a1 , .

, forward lvalue/rvalue , factory . factory rvalue, forward T rvalue. , lvalue factory , T lvalue.

forward :

template <class T> struct identity { typedef T type; }; template <class T> T&& forward(typename identity<T>::type&& a) { return a; }

, . , 95% .

, , , , N1377 .

N1385 .

rvalue ( ), N1690 .

, rvalue , N1952 .

rvalue , N2027 .

rvalue , N1771 .

, rvalue , :
N1856 N1857 N1858 N1859 N1860 N1861 N1862
rvalue (this), N1821 .
 vector<unique_ptr>,   ,     : 

struct indirect_less { template <class T> bool operator()(const T& x, const T& y) {return *x < *y;} }; ... std::vector<std::unique_ptr<A>> v; ... std::sort(v.begin(), v.end(), indirect_less());

unique_ptr , swap ( , ) / . , , . ( , ), .

(perfect forwarding)
, std::shared_ptr . . , , . :

template <class T> std::shared_ptr<T> factory() // { return std::shared_ptr<T>(new T); } template <class T, class A1> std::shared_ptr<T> factory(const A1& a1) // { return std::shared_ptr<T>(new T(a1)); } //
. :

std::shared_ptr<A> p = factory<A>(5);
: , T ?

, factory T .

factory :

template <class T, class A1> std::shared_ptr<T> factory(A1& a1) { return std::shared_ptr<T>(new T(a1)); }
. const factory , (, A1 ) T . , , T . (, std::bind ).

:

std::shared_ptr<A> p = factory<A>(5); // ! A* q = new A(5); // OK
factory , "5" factory , int& rvalue "5". , , .

: AI & const AI &?

, : 4 . 8 . 16 .. .

Rvalue :

template <class T, class A1> std::shared_ptr<T> factory(A1&& a1) { return std::shared_ptr<T>(new T(std::forward<A1>(a1))); }
rvalue factory . const , factory .

: forward ?

move , forward - , , , . a1 , .

, forward lvalue/rvalue , factory . factory rvalue, forward T rvalue. , lvalue factory , T lvalue.

forward :

template <class T> struct identity { typedef T type; }; template <class T> T&& forward(typename identity<T>::type&& a) { return a; }

, . , 95% .

, , , , N1377 .

N1385 .

rvalue ( ), N1690 .

, rvalue , N1952 .

rvalue , N2027 .

rvalue , N1771 .

, rvalue , :
N1856 N1857 N1858 N1859 N1860 N1861 N1862
rvalue (this), N1821 .
vector<unique_ptr>, , :

struct indirect_less { template <class T> bool operator()(const T& x, const T& y) {return *x < *y;} }; ... std::vector<std::unique_ptr<A>> v; ... std::sort(v.begin(), v.end(), indirect_less());

unique_ptr , swap ( , ) / . , , . ( , ), .

(perfect forwarding)
, std::shared_ptr . . , , . :

template <class T> std::shared_ptr<T> factory() // { return std::shared_ptr<T>(new T); } template <class T, class A1> std::shared_ptr<T> factory(const A1& a1) // { return std::shared_ptr<T>(new T(a1)); } //
. :

std::shared_ptr<A> p = factory<A>(5);
: , T ?

, factory T .

factory :

template <class T, class A1> std::shared_ptr<T> factory(A1& a1) { return std::shared_ptr<T>(new T(a1)); }
. const factory , (, A1 ) T . , , T . (, std::bind ).

:

std::shared_ptr<A> p = factory<A>(5); // ! A* q = new A(5); // OK
factory , "5" factory , int& rvalue "5". , , .

: AI & const AI &?

, : 4 . 8 . 16 .. .

Rvalue :

template <class T, class A1> std::shared_ptr<T> factory(A1&& a1) { return std::shared_ptr<T>(new T(std::forward<A1>(a1))); }
rvalue factory . const , factory .

: forward ?

move , forward - , , , . a1 , .

, forward lvalue/rvalue , factory . factory rvalue, forward T rvalue. , lvalue factory , T lvalue.

forward :

template <class T> struct identity { typedef T type; }; template <class T> T&& forward(typename identity<T>::type&& a) { return a; }

, . , 95% .

, , , , N1377 .

N1385 .

rvalue ( ), N1690 .

, rvalue , N1952 .

rvalue , N2027 .

rvalue , N1771 .

, rvalue , :
N1856 N1857 N1858 N1859 N1860 N1861 N1862
rvalue (this), N1821 .
 vector<unique_ptr>,   ,     : 

struct indirect_less { template <class T> bool operator()(const T& x, const T& y) {return *x < *y;} }; ... std::vector<std::unique_ptr<A>> v; ... std::sort(v.begin(), v.end(), indirect_less());

unique_ptr , swap ( , ) / . , , . ( , ), .

(perfect forwarding)
, std::shared_ptr . . , , . :

template <class T> std::shared_ptr<T> factory() // { return std::shared_ptr<T>(new T); } template <class T, class A1> std::shared_ptr<T> factory(const A1& a1) // { return std::shared_ptr<T>(new T(a1)); } //
. :

std::shared_ptr<A> p = factory<A>(5);
: , T ?

, factory T .

factory :

template <class T, class A1> std::shared_ptr<T> factory(A1& a1) { return std::shared_ptr<T>(new T(a1)); }
. const factory , (, A1 ) T . , , T . (, std::bind ).

:

std::shared_ptr<A> p = factory<A>(5); // ! A* q = new A(5); // OK
factory , "5" factory , int& rvalue "5". , , .

: AI & const AI &?

, : 4 . 8 . 16 .. .

Rvalue :

template <class T, class A1> std::shared_ptr<T> factory(A1&& a1) { return std::shared_ptr<T>(new T(std::forward<A1>(a1))); }
rvalue factory . const , factory .

: forward ?

move , forward - , , , . a1 , .

, forward lvalue/rvalue , factory . factory rvalue, forward T rvalue. , lvalue factory , T lvalue.

forward :

template <class T> struct identity { typedef T type; }; template <class T> T&& forward(typename identity<T>::type&& a) { return a; }

, . , 95% .

, , , , N1377 .

N1385 .

rvalue ( ), N1690 .

, rvalue , N1952 .

rvalue , N2027 .

rvalue , N1771 .

, rvalue , :
N1856 N1857 N1858 N1859 N1860 N1861 N1862
rvalue (this), N1821 .
vector<unique_ptr>, , :

struct indirect_less { template <class T> bool operator()(const T& x, const T& y) {return *x < *y;} }; ... std::vector<std::unique_ptr<A>> v; ... std::sort(v.begin(), v.end(), indirect_less());

unique_ptr , swap ( , ) / . , , . ( , ), .

(perfect forwarding)
, std::shared_ptr . . , , . :

template <class T> std::shared_ptr<T> factory() // { return std::shared_ptr<T>(new T); } template <class T, class A1> std::shared_ptr<T> factory(const A1& a1) // { return std::shared_ptr<T>(new T(a1)); } //
. :

std::shared_ptr<A> p = factory<A>(5);
: , T ?

, factory T .

factory :

template <class T, class A1> std::shared_ptr<T> factory(A1& a1) { return std::shared_ptr<T>(new T(a1)); }
. const factory , (, A1 ) T . , , T . (, std::bind ).

:

std::shared_ptr<A> p = factory<A>(5); // ! A* q = new A(5); // OK
factory , "5" factory , int& rvalue "5". , , .

: AI & const AI &?

, : 4 . 8 . 16 .. .

Rvalue :

template <class T, class A1> std::shared_ptr<T> factory(A1&& a1) { return std::shared_ptr<T>(new T(std::forward<A1>(a1))); }
rvalue factory . const , factory .

: forward ?

move , forward - , , , . a1 , .

, forward lvalue/rvalue , factory . factory rvalue, forward T rvalue. , lvalue factory , T lvalue.

forward :

template <class T> struct identity { typedef T type; }; template <class T> T&& forward(typename identity<T>::type&& a) { return a; }

, . , 95% .

, , , , N1377 .

N1385 .

rvalue ( ), N1690 .

, rvalue , N1952 .

rvalue , N2027 .

rvalue , N1771 .

, rvalue , :
N1856 N1857 N1858 N1859 N1860 N1861 N1862
rvalue (this), N1821 .
 vector<unique_ptr>,   ,     : 

struct indirect_less { template <class T> bool operator()(const T& x, const T& y) {return *x < *y;} }; ... std::vector<std::unique_ptr<A>> v; ... std::sort(v.begin(), v.end(), indirect_less());

unique_ptr , swap ( , ) / . , , . ( , ), .

(perfect forwarding)
, std::shared_ptr . . , , . :

template <class T> std::shared_ptr<T> factory() // { return std::shared_ptr<T>(new T); } template <class T, class A1> std::shared_ptr<T> factory(const A1& a1) // { return std::shared_ptr<T>(new T(a1)); } //
. :

std::shared_ptr<A> p = factory<A>(5);
: , T ?

, factory T .

factory :

template <class T, class A1> std::shared_ptr<T> factory(A1& a1) { return std::shared_ptr<T>(new T(a1)); }
. const factory , (, A1 ) T . , , T . (, std::bind ).

:

std::shared_ptr<A> p = factory<A>(5); // ! A* q = new A(5); // OK
factory , "5" factory , int& rvalue "5". , , .

: AI & const AI &?

, : 4 . 8 . 16 .. .

Rvalue :

template <class T, class A1> std::shared_ptr<T> factory(A1&& a1) { return std::shared_ptr<T>(new T(std::forward<A1>(a1))); }
rvalue factory . const , factory .

: forward ?

move , forward - , , , . a1 , .

, forward lvalue/rvalue , factory . factory rvalue, forward T rvalue. , lvalue factory , T lvalue.

forward :

template <class T> struct identity { typedef T type; }; template <class T> T&& forward(typename identity<T>::type&& a) { return a; }

, . , 95% .

, , , , N1377 .

N1385 .

rvalue ( ), N1690 .

, rvalue , N1952 .

rvalue , N2027 .

rvalue , N1771 .

, rvalue , :
N1856 N1857 N1858 N1859 N1860 N1861 N1862
rvalue (this), N1821 .
vector<unique_ptr>, , :

struct indirect_less { template <class T> bool operator()(const T& x, const T& y) {return *x < *y;} }; ... std::vector<std::unique_ptr<A>> v; ... std::sort(v.begin(), v.end(), indirect_less());

unique_ptr , swap ( , ) / . , , . ( , ), .

(perfect forwarding)
, std::shared_ptr . . , , . :

template <class T> std::shared_ptr<T> factory() // { return std::shared_ptr<T>(new T); } template <class T, class A1> std::shared_ptr<T> factory(const A1& a1) // { return std::shared_ptr<T>(new T(a1)); } //
. :

std::shared_ptr<A> p = factory<A>(5);
: , T ?

, factory T .

factory :

template <class T, class A1> std::shared_ptr<T> factory(A1& a1) { return std::shared_ptr<T>(new T(a1)); }
. const factory , (, A1 ) T . , , T . (, std::bind ).

:

std::shared_ptr<A> p = factory<A>(5); // ! A* q = new A(5); // OK
factory , "5" factory , int& rvalue "5". , , .

: AI & const AI &?

, : 4 . 8 . 16 .. .

Rvalue :

template <class T, class A1> std::shared_ptr<T> factory(A1&& a1) { return std::shared_ptr<T>(new T(std::forward<A1>(a1))); }
rvalue factory . const , factory .

: forward ?

move , forward - , , , . a1 , .

, forward lvalue/rvalue , factory . factory rvalue, forward T rvalue. , lvalue factory , T lvalue.

forward :

template <class T> struct identity { typedef T type; }; template <class T> T&& forward(typename identity<T>::type&& a) { return a; }

, . , 95% .

, , , , N1377 .

N1385 .

rvalue ( ), N1690 .

, rvalue , N1952 .

rvalue , N2027 .

rvalue , N1771 .

, rvalue , :
N1856 N1857 N1858 N1859 N1860 N1861 N1862
rvalue (this), N1821 .
 vector<unique_ptr>,   ,     : 

struct indirect_less { template <class T> bool operator()(const T& x, const T& y) {return *x < *y;} }; ... std::vector<std::unique_ptr<A>> v; ... std::sort(v.begin(), v.end(), indirect_less());

unique_ptr , swap ( , ) / . , , . ( , ), .

(perfect forwarding)
, std::shared_ptr . . , , . :

template <class T> std::shared_ptr<T> factory() // { return std::shared_ptr<T>(new T); } template <class T, class A1> std::shared_ptr<T> factory(const A1& a1) // { return std::shared_ptr<T>(new T(a1)); } //
. :

std::shared_ptr<A> p = factory<A>(5);
: , T ?

, factory T .

factory :

template <class T, class A1> std::shared_ptr<T> factory(A1& a1) { return std::shared_ptr<T>(new T(a1)); }
. const factory , (, A1 ) T . , , T . (, std::bind ).

:

std::shared_ptr<A> p = factory<A>(5); // ! A* q = new A(5); // OK
factory , "5" factory , int& rvalue "5". , , .

: AI & const AI &?

, : 4 . 8 . 16 .. .

Rvalue :

template <class T, class A1> std::shared_ptr<T> factory(A1&& a1) { return std::shared_ptr<T>(new T(std::forward<A1>(a1))); }
rvalue factory . const , factory .

: forward ?

move , forward - , , , . a1 , .

, forward lvalue/rvalue , factory . factory rvalue, forward T rvalue. , lvalue factory , T lvalue.

forward :

template <class T> struct identity { typedef T type; }; template <class T> T&& forward(typename identity<T>::type&& a) { return a; }

, . , 95% .

, , , , N1377 .

N1385 .

rvalue ( ), N1690 .

, rvalue , N1952 .

rvalue , N2027 .

rvalue , N1771 .

, rvalue , :
N1856 N1857 N1858 N1859 N1860 N1861 N1862
rvalue (this), N1821 .
vector<unique_ptr>, , :

struct indirect_less { template <class T> bool operator()(const T& x, const T& y) {return *x < *y;} }; ... std::vector<std::unique_ptr<A>> v; ... std::sort(v.begin(), v.end(), indirect_less());

unique_ptr , swap ( , ) / . , , . ( , ), .

(perfect forwarding)
, std::shared_ptr . . , , . :

template <class T> std::shared_ptr<T> factory() // { return std::shared_ptr<T>(new T); } template <class T, class A1> std::shared_ptr<T> factory(const A1& a1) // { return std::shared_ptr<T>(new T(a1)); } //
. :

std::shared_ptr<A> p = factory<A>(5);
: , T ?

, factory T .

factory :

template <class T, class A1> std::shared_ptr<T> factory(A1& a1) { return std::shared_ptr<T>(new T(a1)); }
. const factory , (, A1 ) T . , , T . (, std::bind ).

:

std::shared_ptr<A> p = factory<A>(5); // ! A* q = new A(5); // OK
factory , "5" factory , int& rvalue "5". , , .

: AI & const AI &?

, : 4 . 8 . 16 .. .

Rvalue :

template <class T, class A1> std::shared_ptr<T> factory(A1&& a1) { return std::shared_ptr<T>(new T(std::forward<A1>(a1))); }
rvalue factory . const , factory .

: forward ?

move , forward - , , , . a1 , .

, forward lvalue/rvalue , factory . factory rvalue, forward T rvalue. , lvalue factory , T lvalue.

forward :

template <class T> struct identity { typedef T type; }; template <class T> T&& forward(typename identity<T>::type&& a) { return a; }

, . , 95% .

, , , , N1377 .

N1385 .

rvalue ( ), N1690 .

, rvalue , N1952 .

rvalue , N2027 .

rvalue , N1771 .

, rvalue , :
N1856 N1857 N1858 N1859 N1860 N1861 N1862
rvalue (this), N1821 .
 vector<unique_ptr>,   ,     : 

struct indirect_less { template <class T> bool operator()(const T& x, const T& y) {return *x < *y;} }; ... std::vector<std::unique_ptr<A>> v; ... std::sort(v.begin(), v.end(), indirect_less());

unique_ptr , swap ( , ) / . , , . ( , ), .

(perfect forwarding)
, std::shared_ptr . . , , . :

template <class T> std::shared_ptr<T> factory() // { return std::shared_ptr<T>(new T); } template <class T, class A1> std::shared_ptr<T> factory(const A1& a1) // { return std::shared_ptr<T>(new T(a1)); } //
. :

std::shared_ptr<A> p = factory<A>(5);
: , T ?

, factory T .

factory :

template <class T, class A1> std::shared_ptr<T> factory(A1& a1) { return std::shared_ptr<T>(new T(a1)); }
. const factory , (, A1 ) T . , , T . (, std::bind ).

:

std::shared_ptr<A> p = factory<A>(5); // ! A* q = new A(5); // OK
factory , "5" factory , int& rvalue "5". , , .

: AI & const AI &?

, : 4 . 8 . 16 .. .

Rvalue :

template <class T, class A1> std::shared_ptr<T> factory(A1&& a1) { return std::shared_ptr<T>(new T(std::forward<A1>(a1))); }
rvalue factory . const , factory .

: forward ?

move , forward - , , , . a1 , .

, forward lvalue/rvalue , factory . factory rvalue, forward T rvalue. , lvalue factory , T lvalue.

forward :

template <class T> struct identity { typedef T type; }; template <class T> T&& forward(typename identity<T>::type&& a) { return a; }

, . , 95% .

, , , , N1377 .

N1385 .

rvalue ( ), N1690 .

, rvalue , N1952 .

rvalue , N2027 .

rvalue , N1771 .

, rvalue , :
N1856 N1857 N1858 N1859 N1860 N1861 N1862
rvalue (this), N1821 .
vector<unique_ptr>, , :

struct indirect_less { template <class T> bool operator()(const T& x, const T& y) {return *x < *y;} }; ... std::vector<std::unique_ptr<A>> v; ... std::sort(v.begin(), v.end(), indirect_less());

unique_ptr , swap ( , ) / . , , . ( , ), .

(perfect forwarding)
, std::shared_ptr . . , , . :

template <class T> std::shared_ptr<T> factory() // { return std::shared_ptr<T>(new T); } template <class T, class A1> std::shared_ptr<T> factory(const A1& a1) // { return std::shared_ptr<T>(new T(a1)); } //
. :

std::shared_ptr<A> p = factory<A>(5);
: , T ?

, factory T .

factory :

template <class T, class A1> std::shared_ptr<T> factory(A1& a1) { return std::shared_ptr<T>(new T(a1)); }
. const factory , (, A1 ) T . , , T . (, std::bind ).

:

std::shared_ptr<A> p = factory<A>(5); // ! A* q = new A(5); // OK
factory , "5" factory , int& rvalue "5". , , .

: AI & const AI &?

, : 4 . 8 . 16 .. .

Rvalue :

template <class T, class A1> std::shared_ptr<T> factory(A1&& a1) { return std::shared_ptr<T>(new T(std::forward<A1>(a1))); }
rvalue factory . const , factory .

: forward ?

move , forward - , , , . a1 , .

, forward lvalue/rvalue , factory . factory rvalue, forward T rvalue. , lvalue factory , T lvalue.

forward :

template <class T> struct identity { typedef T type; }; template <class T> T&& forward(typename identity<T>::type&& a) { return a; }

, . , 95% .

, , , , N1377 .

N1385 .

rvalue ( ), N1690 .

, rvalue , N1952 .

rvalue , N2027 .

rvalue , N1771 .

, rvalue , :
N1856 N1857 N1858 N1859 N1860 N1861 N1862
rvalue (this), N1821 .

vector<unique_ptr>, , :

struct indirect_less { template <class T> bool operator()(const T& x, const T& y) {return *x < *y;} }; ... std::vector<std::unique_ptr<A>> v; ... std::sort(v.begin(), v.end(), indirect_less());

unique_ptr , swap ( , ) / . , , . ( , ), .

(perfect forwarding)
, std::shared_ptr . . , , . :

template <class T> std::shared_ptr<T> factory() // { return std::shared_ptr<T>(new T); } template <class T, class A1> std::shared_ptr<T> factory(const A1& a1) // { return std::shared_ptr<T>(new T(a1)); } //
. :

std::shared_ptr<A> p = factory<A>(5);
: , T ?

, factory T .

factory :

template <class T, class A1> std::shared_ptr<T> factory(A1& a1) { return std::shared_ptr<T>(new T(a1)); }
. const factory , (, A1 ) T . , , T . (, std::bind ).

:

std::shared_ptr<A> p = factory<A>(5); // ! A* q = new A(5); // OK
factory , "5" factory , int& rvalue "5". , , .

: AI & const AI &?

, : 4 . 8 . 16 .. .

Rvalue :

template <class T, class A1> std::shared_ptr<T> factory(A1&& a1) { return std::shared_ptr<T>(new T(std::forward<A1>(a1))); }
rvalue factory . const , factory .

: forward ?

move , forward - , , , . a1 , .

, forward lvalue/rvalue , factory . factory rvalue, forward T rvalue. , lvalue factory , T lvalue.

forward :

template <class T> struct identity { typedef T type; }; template <class T> T&& forward(typename identity<T>::type&& a) { return a; }

, . , 95% .

, , , , N1377 .

N1385 .

rvalue ( ), N1690 .

, rvalue , N1952 .

rvalue , N2027 .

rvalue , N1771 .

, rvalue , :
N1856 N1857 N1858 N1859 N1860 N1861 N1862
rvalue (this), N1821 .

vector<unique_ptr>, , :

struct indirect_less { template <class T> bool operator()(const T& x, const T& y) {return *x < *y;} }; ... std::vector<std::unique_ptr<A>> v; ... std::sort(v.begin(), v.end(), indirect_less());

unique_ptr , swap ( , ) / . , , . ( , ), .

(perfect forwarding)
, std::shared_ptr . . , , . :

template <class T> std::shared_ptr<T> factory() // { return std::shared_ptr<T>(new T); } template <class T, class A1> std::shared_ptr<T> factory(const A1& a1) // { return std::shared_ptr<T>(new T(a1)); } //
. :

std::shared_ptr<A> p = factory<A>(5);
: , T ?

, factory T .

factory :

template <class T, class A1> std::shared_ptr<T> factory(A1& a1) { return std::shared_ptr<T>(new T(a1)); }
. const factory , (, A1 ) T . , , T . (, std::bind ).

:

std::shared_ptr<A> p = factory<A>(5); // ! A* q = new A(5); // OK
factory , "5" factory , int& rvalue "5". , , .

: AI & const AI &?

, : 4 . 8 . 16 .. .

Rvalue :

template <class T, class A1> std::shared_ptr<T> factory(A1&& a1) { return std::shared_ptr<T>(new T(std::forward<A1>(a1))); }
rvalue factory . const , factory .

: forward ?

move , forward - , , , . a1 , .

, forward lvalue/rvalue , factory . factory rvalue, forward T rvalue. , lvalue factory , T lvalue.

forward :

template <class T> struct identity { typedef T type; }; template <class T> T&& forward(typename identity<T>::type&& a) { return a; }

, . , 95% .

, , , , N1377 .

N1385 .

rvalue ( ), N1690 .

, rvalue , N1952 .

rvalue , N2027 .

rvalue , N1771 .

, rvalue , :
N1856 N1857 N1858 N1859 N1860 N1861 N1862
rvalue (this), N1821 .
vector<unique_ptr>, , :

struct indirect_less { template <class T> bool operator()(const T& x, const T& y) {return *x < *y;} }; ... std::vector<std::unique_ptr<A>> v; ... std::sort(v.begin(), v.end(), indirect_less());

unique_ptr , swap ( , ) / . , , . ( , ), .

(perfect forwarding)
, std::shared_ptr . . , , . :

template <class T> std::shared_ptr<T> factory() // { return std::shared_ptr<T>(new T); } template <class T, class A1> std::shared_ptr<T> factory(const A1& a1) // { return std::shared_ptr<T>(new T(a1)); } //
. :

std::shared_ptr<A> p = factory<A>(5);
: , T ?

, factory T .

factory :

template <class T, class A1> std::shared_ptr<T> factory(A1& a1) { return std::shared_ptr<T>(new T(a1)); }
. const factory , (, A1 ) T . , , T . (, std::bind ).

:

std::shared_ptr<A> p = factory<A>(5); // ! A* q = new A(5); // OK
factory , "5" factory , int& rvalue "5". , , .

: AI & const AI &?

, : 4 . 8 . 16 .. .

Rvalue :

template <class T, class A1> std::shared_ptr<T> factory(A1&& a1) { return std::shared_ptr<T>(new T(std::forward<A1>(a1))); }
rvalue factory . const , factory .

: forward ?

move , forward - , , , . a1 , .

, forward lvalue/rvalue , factory . factory rvalue, forward T rvalue. , lvalue factory , T lvalue.

forward :

template <class T> struct identity { typedef T type; }; template <class T> T&& forward(typename identity<T>::type&& a) { return a; }

, . , 95% .

, , , , N1377 .

N1385 .

rvalue ( ), N1690 .

, rvalue , N1952 .

rvalue , N2027 .

rvalue , N1771 .

, rvalue , :
N1856 N1857 N1858 N1859 N1860 N1861 N1862
rvalue (this), N1821 .

Source: https://habr.com/ru/post/J226229/


All Articles