[解決済み] 参照渡しより値渡し、std::moveの方が優れている点
質問
私は今C++を学んでいて、悪い習慣を身につけないようにしています。 私が理解したところでは、clang-tidyは多くの"ベストプラクティス"を含んでおり、私はできるだけそれらに固執しようとします(たとえ私が必ずしも理解していなくても なぜ しかし、ここで推奨されていることが理解できているかはわかりません。
チュートリアルにあったこのクラスを使ってみました。
class Creature
{
private:
std::string m_name;
public:
Creature(const std::string &name)
: m_name{name}
{
}
};
これは、clang-tidy からの提案で、参照ではなく値で渡すべきであり
std::move
.
もしそうするならば、次のような提案を受けるでしょう。
name
を参照にすること(毎回コピーされないようにするため)、および
std::move
は何の効果も持たないので
name
は
const
ということで、削除したほうがいいですね。
警告が出ないのは
const
を完全に削除してください。
Creature(std::string name)
: m_name{std::move(name)}
{
}
の唯一の利点は、論理的であるように思えます。
const
は、元の文字列をいじらないようにするためでした(値で渡したので、これは起こりません)。
しかし、私は次のように読みました。
CPlusPlus.com
:
ただし、標準ライブラリでは、移動は、移動元のオブジェクトを有効だが未指定の状態に残すことを意味する。つまり、このような操作の後、移動元のオブジェクトの値は破棄されるか、新しい値が割り当てられるだけであるべきで、それ以外のアクセスは不特定の値を生成します。
さて、こんなコードを想像してみてください。
std::string nameString("Alex");
Creature c(nameString);
なぜなら
nameString
は値で渡される。
std::move
が無効になるのは
name
はコンストラクタの内部で使用され、元の文字列には触れません。しかし、これの利点は何でしょうか?コンテンツがコピーされるのは一度だけのような気がします。
m_name{name}
渡すときに値で渡す場合(そして移動される)。私は、これは値で渡すよりも良いことだと理解しています。
std::move
(2回コピーされるから)。
そこで2つ質問です。
- ここで起こっていることは正しく理解できたでしょうか?
-
を使うと何かいいことがあるのでしょうか?
std::move
を参照渡しで呼び出すよりもm_name{name}
?
解決方法は?
<ブロッククオート- ここで起こっていることは正しく理解されましたか?
はい。
- を使用することの利点は何ですか?
std::move
を参照渡しで呼び出すよりもm_name{name}
?
この関数のシグネチャは、追加のオーバーロードを必要とせず、簡単に把握することができます。このシグネチャは、引数がコピーされることを即座に明らかにします。
const std::string&
の参照がデータメンバとして格納され、後でぶら下がり参照になる可能性があります。また
std::string&& name
と
const std::string&
引数を使用することで、rvalue が関数に渡されたときに不要なコピーを避けることができます。lvalueの渡し方
std::string nameString("Alex");
Creature c(nameString);
を、引数を値で受け取る関数に渡すと、コピーと移動の構文が1つずつ発生します。同じ関数にrvalueを渡すと
std::string nameString("Alex");
Creature c(std::move(nameString));
は、2回の移動構文が発生します。これに対して、関数パラメータが
const std::string&
rvalueの引数を渡す場合でも、常にコピーが存在する。これは、引数の型が移動構築しにくいものである限り、明らかに有利である(例えば
std::string
).
しかし、考慮すべきマイナス面もあります。関数の引数を(初期化するのではなく)別の変数に代入するような関数では、この理屈は成り立ちません。
void setName(std::string name)
{
m_name = std::move(name);
}
というリソースの割り当てを解除することになります。
m_name
は、再割り当てされる前に参照しています。Effective Modern C++のItem 41を読むことをお勧めしますし、また
この質問
.
関連
-
[解決済み】構造体のベクター初期化について
-
[解決済み】C++エラーです。"配列は中括弧で囲まれたイニシャライザーで初期化する必要がある"
-
[解決済み】抽象クラス型の無効なnew-expression
-
[解決済み】エラー。switchステートメントでcaseラベルにジャンプする
-
[解決済み] [Solved] インクルードファイルが開けません。'stdio.h' - Visual Studio Community 2017 - C++ Error
-
[解決済み】標準ライブラリにstd::endlに相当するタブはあるか?
-
[解決済み] std::move()とは何ですか?また、どのような場合に使用するのですか?
-
[解決済み] const std::string & をパラメータとして渡す時代は終わったのでしょうか?
-
[解決済み] Intel CPU の _mm_popcnt_u64 で、32 ビットのループカウンターを 64 ビットに置き換えると、パフォーマンスが著しく低下します。
-
[解決済み] なぜ 'this' はポインターで、参照ではないのですか?
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】 unsigned int vs. size_t
-
[解決済み】変数 '' を抽象型 '' と宣言できない。
-
[解決済み】C++の変数はイニシャライザーを持っているが、不完全な型?
-
[解決済み】C++の余分な資格エラー
-
[解決済み】エラー:free(): 次のサイズが無効です(fast)。
-
[解決済み】クラスのコンストラクタへの未定義参照、.cppファイルの修正も含む
-
[解決済み] gdbを使用してもデバッグシンボルが見つからない
-
[解決済み] 数値定数の前にunqualified-idを付けて、数値を定義することを期待する。
-
[解決済み】std::cin.getline( ) vs. std::cin
-
[解決済み】Eclipse IDEでC++エラー「nullptrはこのスコープで宣言されていません」が発生する件