[解決済み] コンストラクタや関数に unique_ptr 引数を渡すにはどうしたらいいですか?
質問
C++11のmoveセマンティクスに慣れていないため、以下の処理方法がよくわかりません。
unique_ptr
パラメータを使用します。このクラスが自分自身を参照することを考えてみましょう。
#include <memory>
class Base
{
public:
typedef unique_ptr<Base> UPtr;
Base(){}
Base(Base::UPtr n):next(std::move(n)){}
virtual ~Base(){}
void setNext(Base::UPtr n)
{
next = std::move(n);
}
protected :
Base::UPtr next;
};
を取る関数はこのように書けばいいのでしょうか?
unique_ptr
の引数を取ることができますか?
また
std::move
を呼び出すコードで使用できますか?
Base::UPtr b1;
Base::UPtr b2(new Base());
b1->setNext(b2); //should I write b1->setNext(std::move(b2)); instead?
解決方法は?
一意なポインターを引数として受け取るために可能な方法と、それに関連する意味を説明します。
(A) 値によって
Base(std::unique_ptr<Base> n)
: next(std::move(n)) {}
ユーザーがこれを呼び出すには、次のいずれかを行う必要があります。
Base newBase(std::move(nextBase));
Base fromTemp(std::unique_ptr<Base>(new Base(...));
ユニークポインタを値で取るということは
転送
ポインタの所有権は、問題の関数/オブジェクト/その他にあります。後
newBase
が構築されます。
nextBase
であることが保証されています。
空
. あなたはそのオブジェクトを所有していませんし、そのポインタさえももう持っていません。それはもうありません。
これは、パラメータを値で受け取るので確実です。
std::move
は実際には
移動
のようなもので、単なる派手なキャストです。
std::move(nextBase)
を返します。
Base&&
へのr値参照である。
nextBase
. それだけなんです。
なぜなら
Base::Base(std::unique_ptr<Base> n)
は引数を r-value reference ではなく value で取るので、C++ は自動的にテンポラリを構築してくれます。これは
std::unique_ptr<Base>
から
Base&&
を介して関数に与えた
std::move(nextBase)
. この仮設を作ることで、実際に
動く
の値を
nextBase
を関数の引数
n
.
(B) 非恒等式l値参照によるもの
Base(std::unique_ptr<Base> &n)
: next(std::move(n)) {}
これは実際のl値(名前付き変数)に対して呼び出されなければなりません。このように一時的なものでは呼び出すことができません。
Base newBase(std::unique_ptr<Base>(new Base)); //Illegal in this case.
この意味は、他の非恒等式参照の使い方と同じである。 または ポインタの所有権を主張します。このコードを考えると
Base newBase(nextBase);
という保証はありません。
nextBase
は空です。それは
かもしれない
空っぽかもしれないし、空っぽでないかもしれない。それは本当に
Base::Base(std::unique_ptr<Base> &n)
がしたいのです。そのため、関数のシグネチャを見ただけでは、何が起こるのかがよくわかりません。
そのため、インターフェースとしてはあまりお勧めできません。
(C) const l値参照による
Base(std::unique_ptr<Base> const &n);
実装を示さないのは、あなたが
できない
からの移動
const&
. を渡すことで
const&
にアクセスできることを意味しています。
Base
はポインタを経由していますが
ストア
をどこかに置く。所有権を主張することもできません。
これは便利です。あなたの特定のケースに当てはまるとは限りませんが、誰かにポインタを渡して、そのポインタが
できない
(のようなC++のルールを破ることなく)。
const
) 所有権を主張する。保存することはできません。他の人に渡すことはできますが、他の人も同じ規則に従わなければなりません。
(D) r値参照による
Base(std::unique_ptr<Base> &&n)
: next(std::move(n)) {}
これは、"by non-const l-value reference"の場合とほぼ同じです。違うのは2点です。
-
あなたは できる テンポラリーを渡す。
Base newBase(std::unique_ptr<Base>(new Base)); //legal now..
-
あなた 必須 使用
std::move
は、一時的でない引数を渡すときに使用します。
本当に問題なのは後者です。もし、この行を見たら
Base newBase(std::move(nextBase));
この行が完了した後、あなたは合理的な期待を持っています。
nextBase
は空であるべきです。から移動しているはずです。結局のところ、あなたはその
std::move
そこに座って、移動が起こったことを伝えているのです。
問題は、そうなっていないことです。それは 保証 から移動していること。それは かもしれません から移動していますが、ソースコードを見なければわかりません。関数のシグネチャだけではわかりません。
推薦の言葉
-
(A)価値観で。
もし、ある機能が主張することを意味するのであれば
所有権
の
unique_ptr
の場合、値で受け取る。 -
(C) const l値参照によって。
もし、ある関数が単に
unique_ptr
は、その関数が実行されている間、それをconst&
. または&
またはconst&
を使用するのではなく、実際に指された型に対してunique_ptr
. -
(D)r値参照で。
関数が所有権を主張したりしなかったりする場合(内部コードのパスに依存する)、その関数を
&&
. しかし、私は可能な限りこれをしないことを強くお勧めします。
unique_ptrの操作方法
をコピーすることはできません。
unique_ptr
. 移動のみ可能です。これを行うには、適切な方法は
std::move
標準ライブラリ関数
を取ると
unique_ptr
を値で指定すると、そこから自由に移動することができます。しかし、移動が実際に行われないのは
std::move
. 次のような文章を考えてみましょう。
std::unique_ptr<Base> newPtr(std::move(oldPtr));
これは実際には2つのステートメントです。
std::unique_ptr<Base> &&temporary = std::move(oldPtr);
std::unique_ptr<Base> newPtr(temporary);
(注:一時的でないr値の参照は実際のr値ではないので、上記のコードは技術的にコンパイルできません。これはデモのためだけにあります)。
は
temporary
へのr値参照に過ぎない。
oldPtr
. それは
コンストラクタ
の
newPtr
移動が発生する場所。
unique_ptr
のmoveコンストラクタ(このコンストラクタには
&&
を自分自身に置き換えることで、実際の動きを行っています。
もし、あなたが
unique_ptr
の値で、それをどこかに保存したい場合は
必ず
使用
std::move
を使用して保存します。
関連
-
[解決済み] C++で、あるコンストラクタを別のコンストラクタから呼び出す(コンストラクタ・チェイニングを行う)ことは可能ですか?
-
[解決済み] 文字列の単語を反復処理するにはどうすればよいですか?
-
[解決済み] 1ビットのセット、クリア、トグルはどのように行うのですか?
-
[解決済み] Node.jsのプログラムにコマンドライン引数を渡すにはどうしたらいいですか?
-
[解決済み] Bashでコマンドライン引数を解析するには?
-
[解決済み] C++11では、標準化されたメモリモデルが導入されました。その意味するところは?そして、C++プログラミングにどのような影響を与えるのでしょうか?
-
[解決済み] バッチファイルに引数を渡すにはどうしたらいいですか?
-
[解決済み] Bash関数にパラメータを渡す
-
[解決済み] 関数からunique_ptrを返す
-
[解決済み】JavaScriptの関数にデフォルトのパラメータ値を設定する
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】C++でint型に無限大を設定する
-
[解決済み】C++ 非推奨の文字列定数から「char*」への変換について
-
[解決済み】識別子 "string "は未定義?
-
[解決済み] 非常に基本的なC++プログラムの問題 - バイナリ式への無効なオペランド
-
[解決済み】リンカーエラーです。"リンカ入力ファイルはリンクが行われていないため未使用"、そのファイル内の関数への未定義参照
-
[解決済み】エラー:free(): 次のサイズが無効です(fast)。
-
[解決済み】C++ - ステートメントがオーバーロードされた関数のアドレスを解決できない。
-
[解決済み】デバッグアサーションに失敗しました
-
[解決済み] ムーブセマンティクスとは何ですか?
-
[解決済み] C++11のT&&(ダブルアンパサンド)の意味とは?