std::vector
最近、Herb Sutter 氏の講演を聞きましたが、彼は、passやstd::string
by する理由はconst &
ほとんどなくなったと述べています。彼は、次のような関数を書く方が今は望ましいと示唆しています。
std::string do_something ( std::string inval )
{
std::string return_val;
// ... do stuff ...
return return_val;
}
return_val
は関数が戻る時点では右辺値になるため、非常にコストのかからない移動セマンティクスを使用して返すことができることは理解しています。ただし、inval
は参照 (通常はポインターとして実装されます) のサイズよりもはるかに大きくなります。これは、std::string
ヒープへのポインターや短い文字列の最適化用のメンバーなど、さまざまなコンポーネントが に含まれていたためですchar[]
。そのため、参照渡しは依然として良いアイデアであるように思われます。
ハーブがなぜこう言ったのか説明できる人はいますか?
ベストアンサー1
ハーブがそう言ったのは、このような事例があったからです。
A
関数 を呼び出しB
、関数 を呼び出す関数があるとしますC
。そして、 にA
文字列を渡します。は を知らず、気にも留めません。が知っているのは だけです。つまり、 はの実装の詳細です。B
C
A
C
A
B
C
B
A が次のように定義されているとします。
void A()
{
B("value");
}
B と C が文字列を取る場合const&
、次のようになります。
void B(const std::string &str)
{
C(str);
}
void C(const std::string &str)
{
//Do something with `str`. Does not store it.
}
すべて順調です。ポインターを渡すだけで、コピーや移動は行われず、誰もが満足しています。文字列を保存しないため、C
を受け取ります。単にそれを使用します。const&
ここで、1 つの簡単な変更を加えます。C
文字列をどこかに保存する必要があります。
void C(const std::string &str)
{
//Do something with `str`.
m_str = str;
}
こんにちは、コピーコンストラクタと潜在的なメモリ割り当て(短い文字列の最適化 (SSO))。C++11 の移動セマンティクスは、不必要なコピー構築を排除できるようにするはずですよね? そして、一時的なものを渡します。データをコピーする必要があるA
理由はありません。渡されたものを持って逃げるだけです。C
ただし、それはできません。時間がかかるからですconst&
。
C
パラメータを値で受け取るように変更すると、B
そのパラメータにコピーが行われるだけで、何も得られません。
str
したがって、すべての関数に値渡しして、データをシャッフルするだけであればstd::move
、この問題は発生しません。誰かがそれを保持したいのであれば、保持できます。保持したくない場合は、仕方ありません。
コストは高くなりますか? はい。値への移動は参照を使用するよりもコストがかかります。コピーよりもコストはかかりませんか? SSO を使用した小さな文字列の場合はそうではありません。実行する価値はありますか?
それはユースケースによって異なります。メモリ割り当てがどの程度嫌いですか?