[解決済み] 引数として共有ポインタを渡す
質問
共有ポインタでラップしたオブジェクトを宣言した場合。
std::shared_ptr<myClass> myClassObject(new myClass());
で、それをメソッドの引数として渡したいと思いました。
DoSomething(myClassObject);
//the called method
void DoSomething(std::shared_ptr<myClass> arg1)
{
arg1->someField = 4;
}
上記は単にshared_ptの参照カウントをインクリメントするだけで、すべてがクールになるのでしょうか?それとも、ポインタがぶら下がったままになるのでしょうか?
あなたはまだこれを行うことになっていますか?
DoSomething(myClassObject.Get());
void DoSomething(std::shared_ptr<myClass>* arg1)
{
(*arg1)->someField = 4;
}
2番目の方法は、(スマートポインタ全体ではなく)1つのアドレスだけをコピーすればよいので、より効率的かもしれないと思いますが、1番目の方法はより読みやすく、パフォーマンスの限界を超えることは予想されません。私はただ、それについて何か危険なことがないことを確認したいだけです。
ありがとうございます。
どのように解決するのですか?
<ブロッククオート関数に共有ポインタを渡したいのですが、どうすればよいですか。あなたはそれを私を助けることができますか?
もちろん、私はあなたを助けることができます。あなたは C++ の所有権のセマンティクスをある程度理解していると思います。それは本当ですか?
ええ、この話題にはそれなりに慣れています。
よかった。
OK、2つの理由しか思い浮かばないが、そのうちの1つは
shared_ptr
の引数を取る必要があります。
- この関数はオブジェクトの所有権を共有することを望んでいます。
-
この関数は、特に
shared_ptr
s.
どれに興味がありますか?
<ブロッククオート一般的な答えを求めているので、実は両方に興味があるんです。しかし、ケース2の意味が気になりますね。
このような関数の例としては
std::static_pointer_cast
やカスタムコンパレータ、述語などがあります。例えば、ベクターからすべてのユニークなshared_ptrを見つける必要がある場合、そのような述語が必要です。
ああ、関数が実際にスマートポインタそのものを操作する必要があるとき。
その通りです。
<ブロッククオートその場合、参照渡しでいいと思います。
そうですね。そして、ポインタを変更しないのであれば、const参照で渡したいところです。所有権を共有する必要がないので、コピーする必要はありません。それがもうひとつのシナリオです。
OK、了解しました。もう1つのシナリオについて話しましょう。
所有権を共有するもの?OKです。どのように所有権を共有するかというと
shared_ptr
?
コピーすることで
次に、この関数は、コピーを作成するために
shared_ptr
になるのですが、正しいですか?
明らかに だからconstの参照で渡して、ローカル変数にコピーする?
いいえ、それは悲観的です。参照で渡された場合、関数は手動でコピーを作成する以外に選択肢はありません。値で渡された場合、コンパイラはコピーと移動の間の最適な選択を選び、自動的に実行します。だから、値で渡す。
良い指摘だ。覚えておかなければなりませんね"。 スピードが欲しい?価値でパス。 の記事をもっと頻繁に思い出す必要があります。
待てよ、もし関数が
shared_ptr
をメンバ変数に格納したらどうでしょう?冗長なコピーになりませんか?
この関数では、単に
shared_ptr
引数をそのストレージに移動します。を移動することは
shared_ptr
を移動することは、参照カウントを変更しないので、安価です。
ああ、いい考えですね。
しかし、私は3つ目のシナリオを考えています。
shared_ptr
を操作したくない、所有権も共有したくない場合はどうでしょうか?
その場合
shared_ptr
は関数に全く関係ありません。もしポインティを操作したいのであれば、ポインティを取り、呼び出し側がどのような所有権のセマンティクスを望むかを選択できるようにします。
そして、ポインティを参照で取るべきか、値で取るべきか?
通常のルールが適用されます。スマートポインタは何も変えません。
コピーするなら値で渡し、コピーを避けたいなら参照で渡す。
そうですね。
<ブロッククオートふむ。まだ別のシナリオを忘れているようですね。所有権を共有したいが、ある条件によってのみ共有したい場合はどうすればよいでしょうか。
ああ、面白いエッジケースですね。これが頻繁に起こるとは思っていません。しかし、それが起こったとき、値で渡して、必要なければコピーを無視するか、参照で渡して、必要ならコピーを作成することができます。
最初のオプションで1つの冗長なコピーを危険にさらし、2番目のオプションで潜在的な動きを失います。ケーキを食べながらそれを持つことはできないのでしょうか?
もしそれが本当に重要な状況であれば、2つのオーバーロードを提供することができます。1つはconst lvalueの参照を取り、もう1つはrvalueの参照を取ります。1つはコピー、もう1つは移動です。パーフェクトフォワード関数テンプレートは別の選択肢です。
これで、考えられるシナリオはすべて網羅できたと思います。ありがとうございました。
関連
-
[解決済み】C++ - 解放されるポインタが割り当てられていないエラー
-
[解決済み] error: 'ostream' does not name a type.
-
[解決済み】テンプレートの引数1が無効です(Code::Blocks Win Vista) - テンプレートは使いません。
-
[解決済み】#include<iostream>は存在するのですが、「識別子 "cout "は未定義です」というエラーが出ます。なぜですか?
-
[解決済み】C++の余分な資格エラー
-
[解決済み】指定範囲内の乱数で配列を埋める(C++)
-
[解決済み】CMakeエラー at CMakeLists.txt:30 (project)。CMAKE_C_COMPILER が見つかりませんでした。
-
[解決済み】VC++の致命的なエラーLNK1168:書き込みのためにfilename.exeを開くことができません。
-
[解決済み] const std::string & をパラメータとして渡す時代は終わったのでしょうか?
-
[解決済み] スタティック・ライブラリとシェアード・ライブラリの違い?
最新
-
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++の場合)
-
[解決済み】IntelliSense:オブジェクトに、メンバー関数と互換性のない型修飾子がある
-
[解決済み】デバッグアサーションに失敗しました。C++のベクトル添え字が範囲外
-
[解決済み】ファイルから整数を読み込んで配列に格納する C++ 【クローズド
-
[解決済み】エラー:不完全な型へのメンバーアクセス:前方宣言の
-
[解決済み】Visual Studioのデバッガーエラー。プログラムを開始できません 指定されたファイルが見つかりません
-
[解決済み】c++で.txtファイルから2次元の配列に読み込む
-
[解決済み] shared_ptr<Derived>をshared_ptr<Base>として渡す。
-
[解決済み] C++ - std::shared_ptr または boost::shared_ptr への参照の渡し方