[解決済み] std::reference_wrapperとシンプルポインタの違い?
質問
なぜ
std::reference_wrapper
? どこで使うべき?単純なポインタとどう違うのですか?単純なポインタと比較して、その性能はどうですか?
どのように解決するのですか?
std::reference_wrapper
は、テンプレートと組み合わせて使用すると便利です。これは、オブジェクトへのポインタを格納することでオブジェクトをラップし、通常のセマンティクスを模倣しながら再割り当てとコピーを可能にします。また、特定のライブラリテンプレートには、オブジェクトの代わりに参照を格納するように指示します。
ファンクタをコピーするSTLのアルゴリズムについて考えてみましょう。ファンクタ自身の代わりにファンクタを参照する参照ラッパーを渡すだけで、そのコピーを回避することができます。
unsigned arr[10];
std::mt19937 myEngine;
std::generate_n( arr, 10, std::ref(myEngine) ); // Modifies myEngine's state
これがうまくいくのは
-
...
reference_wrapper
s オーバーロードoperator()
で、これらは参照する関数オブジェクトと同じように呼び出すことができます。std::ref(myEngine)() // Valid expression, modifies myEngines state
-
... (通常の参照と異なり) コピー (および割り当て) は
reference_wrappers
はポインティを割り当てるだけです。int i, j; auto r = std::ref(i); // r refers to i r = std::ref(j); // Okay; r refers to j r = std::cref(j); // Error: Cannot bind reference_wrapper<int> to <const int>
参照ラッパーをコピーすることは、実質的にポインタをコピーすることと同じであり、それは限りなく安いものです。それを使うことに内在する全ての関数呼び出し(例えば
operator()
へのもの) は、ワンライナーであるため、単にインライン化されるべきです。
reference_wrapper
は
std::ref
と
std::cref
:
int i;
auto r = std::ref(i); // r is of type std::reference_wrapper<int>
auto r2 = std::cref(i); // r is of type std::reference_wrapper<const int>
template引数には,参照されるオブジェクトの型とcv-qualificationを指定します.
r2
は
const int
への参照のみを生成します。
const int
. ラッパーを参照するための呼び出しは
const
ファンクタが含まれる参照ラッパーを呼び出すと
const
メンバー関数
operator()
s.
Rvalueイニシャライザーは、許可することは良いことよりも害が大きいので、許可されません。rvalue はいずれにせよ移動されるので ( コピー消去を保証する は部分的に回避されます)、私たちはセマンティクスを改善しません。しかし、参照ラッパーは被指摘者の寿命を延長しないので、ぶら下がりポインタを導入することはできます。
ライブラリの相互作用
前述したように
make_tuple
に参照を保存するように指示することができます。
tuple
に対応する引数を渡すことで
reference_wrapper
:
int i;
auto t1 = std::make_tuple(i); // Copies i. Type of t1 is tuple<int>
auto t2 = std::make_tuple(std::ref(i)); // Saves a reference to i.
// Type of t2 is tuple<int&>
とは若干異なることに注意してください。
forward_as_tuple
: ここでは、引数としてのrvalueは許可されていません。
std::bind
は同じ挙動を示します。引数はコピーされませんが、もし引数が
reference_wrapper
. その引数(あるいはファンクタ!)がコピーされる必要がなく、スコープ内にとどまり、その間に
bind
-ファンクタが使われている間、スコープに残る場合に便利です。
通常のポインタとの違い
-
構文的な間接指示の追加レベルはありません。ポインターは、それらが参照するオブジェクトへの lvalue を得るためにデリファレンスされなければなりません。
reference_wrapper
には暗黙の 変換演算子 を持ち、ラップしているオブジェクトのように呼び出すことができます。int i; int& ref = std::ref(i); // Okay
-
reference_wrapper
は、ポインタとは異なり、NULL状態を持ちません。初期化には 参照か別のreference_wrapper
.std::reference_wrapper<int> r; // Invalid
-
類似点としては、浅いコピーセマンティクスが挙げられます。ポインタと
reference_wrapper
は再割り当てすることができます。
関連
-
[解決済み】C-stringを使用すると警告が表示される。"ローカル変数に関連するスタックメモリのアドレスが返される"
-
[解決済み] [Solved] Error C1083: Cannot open include file: 'stdafx.h'
-
[解決済み] コピーアンドスワップ慣用句とは?
-
[解決済み] C++11では、標準化されたメモリモデルが導入されました。その意味するところは?そして、C++プログラミングにどのような影響を与えるのでしょうか?
-
[解決済み] スマートポインターとは何ですか?
-
[解決済み] const int*、const int * const、int const *の違いは何ですか?
-
[解決済み] C++11の'typedef'と'using'の違いは何ですか?
-
[解決済み] nullptrとは一体何ですか?
-
[解決済み] リファレンスとポインタの使い分け
-
[解決済み】なぜC++プログラマは'new'の使用を最小限に抑えなければならないのでしょうか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] テスト
-
[解決済み] エラーが発生する。ISO C++は型を持たない宣言を禁じています。
-
[解決済み】C++でユーザー入力を待つ【重複あり
-
[解決済み】C++ 式はポインタからオブジェクトへの型を持っている必要があります。
-
[解決済み】IntelliSense:オブジェクトに、メンバー関数と互換性のない型修飾子がある
-
[解決済み】'cout'は型名ではない
-
[解決済み] 数値定数の前にunqualified-idを付けて、数値を定義することを期待する。
-
[解決済み】Enterキーを押して続行する
-
[解決済み] 警告:暗黙の定数変換でのオーバーフロー
-
[解決済み] ヌル参照は可能ですか?