4

コンパイラの作成者から集めたものに基づいて、効率の点で値型は参照/ポインターよりもはるかに好まれます。

これは、エイリアシング、外部で変更されたメモリ (ポインターが参照する)、ポインター逆参照のコストなどを気にする必要がない場合、値型の方が簡単に推論できるという事実に由来します。そのような懸念は理解していますが、特定のケースに関してまだいくつか質問があると言わざるを得ません。

ケース #0

void foo(const float& f) さて、ここに参照がありますが、それは一定です! 確かに、私たちはそれの一定のビュー (参照) を持っているので、外部的には変更される可能性がありますが、それはマルチスレッドの世界でのみ発生する可能性があり、同期プリミティブが使用されていない場合、コンパイラがそれをまったく考慮する必要があるかどうかはわかりません. 明らかに、float 変数への別のポインター/参照を内部的に使用した場合、fパラメーターを変更するリスクがある可能性があります。コンパイラはこのパラメーターを安全なものとして扱うことができますか (ref/ptr を使用して内部的に浮動させることはないと仮定します)?

ケース #1

void foo(vector<int> f) C++11/14 プログラマーの観点から言えば、vectorを安全に関数に移動できることはわかっています。ご存知のように、コンテナは内部的に配列へのポインタを保持しています。vectorのコピーを取得したばかりなので、コンパイラはポインターを安全 (外部からの変更なし) として扱うので、その所有者は私たちだけでしょうか?

言い換えれば、コピーされたオブジェクトが安全なものとして扱われる (論理的にはオブジェクトのクローンを作成するため)、またはコンパイラがそのような仮定を行うことを許可されておらず ptr/ref メンバーを潜在的に危険なものとして扱わなければならないcopy ctor/op が適切なコピーを作成していない可能性があります。プログラマーは、共有リソースをコピーするときにそれらを処理する責任を負うべきではありませんか?

要点:

定数ポインター/参照およびコピーされた複雑なオブジェクトは、一般にプリミティブのコピーよりも低速であるため、パフォーマンスが重要なコードではできる限り回避する必要があります。それとも、わずかに効率が悪いだけで、心配する必要はありませんか?

4

3 に答える 3

3

現代の C++ の一般的な規則として:

  1. 、またはなどの(コピーするのが安い)プリミティブ型の場合、それが入力読み取り専用)パラメーターの場合は、値で渡すだけです:intfloatdouble

    inline double Square(double x)
    {
        return x*x;
    }
    
  2. 代わりに、入力パラメーターの型がコピーするのは安くないが、移動するのは安くない場合、たとえばstd::vectorstd::stringなどの場合は、2 つのサブケースを検討してください。

    を。関数が値を監視しているだけの場合は、参照渡ししconstます(これにより、無駄でコストがかかる可能性のあるディープコピーを防ぐことができます)。

    double Average(const std::vector<double> & v)
    {
        .... // compute average of elements in v (which is read-only)
    }
    

    b. 関数がパラメーターのローカル コピーを取得している場合は、値渡しおよび値std::moveから渡します(移動セマンティクスのおかげで最適化が可能になります)。

    void Person::SetName(std::string name)
    {
        m_name = std::move(name);
    }
    
于 2013-08-01T08:39:07.963 に答える
2

(コメントとして開始しましたが、収まりません。)

ケース #0 はすでに死に至るまで議論されています。たとえば、次のようになります。

プリミティブ型を参照渡しするのは非生産的ですか?

これはすでに他の2つの質問の複製です。特に、この回答はあなたのケース #0 に対する良い回答でもあると思います。関連する質問:

ケース #1 は私にはわかりません:コピーが必要ですか、それとも移動したいですか? この 2 つには大きな違いがあり、何を書いているのか、どちらが必要なのかは不明です。

参照で十分なのに、代わりにコピーを行うと、リソースが無駄になります。

ディープ コピーを作成する必要がある場合は、それだけです。参照も移動も役に立ちません。

この回答を読んで、ケース #1 を修正してください。

于 2013-08-01T08:54:36.357 に答える