C++のビュー型:const&で渡すか、値で渡すか?
質問
これは最近、コードレビューの議論で出てきましたが、満足のいく結論には至りませんでした。問題の型は、C++ の string_view TS の類似品です。それらは、いくつかのカスタム関数で装飾された、ポインターと長さの周りの単純な非所有ラッパーです。
#include <cstddef>
class foo_view {
public:
foo_view(const char* data, std::size_t len)
: _data(data)
, _len(len) {
}
// member functions related to viewing the 'foo' pointed to by '_data'.
private:
const char* _data;
std::size_t _len;
};
このようなビュータイプ (近日公開予定の string_view と array_view タイプを含む) を値で渡すか const 参照で渡すか、どちらを選ぶかについて疑問が生じました。
値で渡すことを支持する議論は、「より少ないタイピング」、「ビューが意味のある変異を持つ場合、ローカル コピーを変異させることができる」、および「おそらく効率は劣らない」に相当しました。
pass-by-const-referenceを支持する議論は、'const&によってオブジェクトを渡すことがより慣用的である'、および'おそらく効率的でない'に相当する。
値またはconst参照によって慣用的なビュー型を渡すことがより良いかどうかという点で、議論を決定的に一方に振り向けるかもしれない追加の考慮事項がありますか。
この質問については、C++11 または C++14 のセマンティクス、および十分に近代的なツールチェーンとターゲット アーキテクチャなどを想定するのが安全です。
どのように解決するのですか?
迷ったら、値で渡す。
さて、迷うことはめったにないはずです。
多くの場合、値は渡すのに高価で、ほとんど利益を与えません。 時には、他の場所に保存された変異する可能性のある値への参照が実際に必要なこともあります。 多くの場合、一般的なコードでは、コピーが高価な操作であるかどうか分からないので、そうでない側を選択します。
疑問があるときに値で渡すべき理由は、値が推論しやすいからです。 参照(たとえ
const
への参照は、アルゴリズムの途中で関数のコールバックを呼び出したりすると変異する可能性があり、単純な関数に見えるものが複雑な混乱に陥る可能性があります。
この場合、すでに暗黙の参照バインド (表示中のコンテナの内容へのバインド) があります。 別の暗黙の参照バインド(コンテナを覗くビューオブジェクトへの)を追加することは、すでに複雑になっているため、悪いことではありません。
最後に、コンパイラーは値への参照についてよりも値についてよりよく推論することができます。 ローカルに分析されたスコープを (関数ポインターのコールバックによって) 離れる場合、コンパイラーは const 参照に格納された値が完全に変更されているかもしれないと推定しなければなりません (反対のことを証明できない場合)。 誰もそれへのポインターを取らない自動ストレージ内の値は、同様の方法で変更されないと仮定することができます - 外部スコープからそれにアクセスして変更する定義された方法はないので、そのような変更は発生しないと仮定することができます。
値を値として渡す機会があるときは、シンプルさを受け入れましょう。 めったにないことですが。
関連
-
[解決済み] エラーが発生する。ISO C++は型を持たない宣言を禁じています。
-
[解決済み] string does not name a type Errorが発生するのはなぜですか?
-
[解決済み] 非常に基本的なC++プログラムの問題 - バイナリ式への無効なオペランド
-
[解決済み】 while(cin) と while(cin >> num) の違いは何ですか?)
-
[解決済み] 変数を参照渡しする方法を教えてください。
-
[解決済み] const int*、const int * const、int const *の違いは何ですか?
-
[解決済み] C++のPOD型とは何ですか?
-
[解決済み] constexpr` と `const` の相違点
-
[解決済み] const std::string & をパラメータとして渡す時代は終わったのでしょうか?
-
[解決済み】C#でオブジェクトを参照または値で渡す
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】LLVMで暗黙のうちに削除されたコピーコンストラクタの呼び出し
-
[解決済み】非静的メンバ関数への参照を呼び出す必要がある
-
[解決済み】C-stringを使用すると警告が表示される。"ローカル変数に関連するスタックメモリのアドレスが返される"
-
[解決済み】 != と =! の違いと例(C++の場合)
-
[解決済み] string does not name a type Errorが発生するのはなぜですか?
-
[解決済み】fpermissiveフラグは何をするのですか?
-
[解決済み】C++ - ステートメントがオーバーロードされた関数のアドレスを解決できない。
-
[解決済み】 while(cin) と while(cin >> num) の違いは何ですか?)
-
[解決済み】警告 - 符号付き整数式と符号なし整数式の比較
-
[解決済み] スタックアロケーションにより初期化されていない値が作成された