1. ホーム
  2. c++

C++のビュー型:const&で渡すか、値で渡すか?

2023-08-26 11:25:08

質問

これは最近、コードレビューの議論で出てきましたが、満足のいく結論には至りませんでした。問題の型は、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 参照に格納された値が完全に変更されているかもしれないと推定しなければなりません (反対のことを証明できない場合)。 誰もそれへのポインターを取らない自動ストレージ内の値は、同様の方法で変更されないと仮定することができます - 外部スコープからそれにアクセスして変更する定義された方法はないので、そのような変更は発生しないと仮定することができます。

値を値として渡す機会があるときは、シンプルさを受け入れましょう。 めったにないことですが。