8

値渡しか const 参照のどちらで渡すかを決定するための適切なルールのセットがあります。

  • 関数が副作用として引数を変更する場合は、非 const 参照で取得します。
  • 関数がその引数を変更せず、引数がプリミティブ型である場合は、値で受け取ります。
  • それ以外の場合は、次の場合を除き、const 参照で取得します。関数が const 参照のコピーを作成する必要がある場合は、値で取得します。

次のようなコンストラクターの場合、それを決定する方法は?

class A
{
public:
    A(string str) : mStr(str) {} // here which is better, 
                                 // pass by value or const reference?

    void setString(string str)  { mStr = str; } // how about here?

private:
    string mStr;
};
4

4 に答える 4

4

この特定のケースでは、C++11 と文字列の構築/割り当てを移動すると仮定すると、引数を値で取得し、コンストラクターのメンバーに移動する必要があります。

A::A(string str) : mStr(std::move(str)) {}

セッターの場合は少しトリッキーで、本当にすべてを最適化したい/必要があるかどうかはわかりません...最大限に最適化したい場合は、右辺値参照と別の2つのオーバーロードを提供できますconst 左辺値参照。とにかく、 const lvalue 参照はおそらく十分なアプローチです:

void A::setString(string const& str) { mStr = str; }

違いはなぜですか?

コンストラクターの場合、メンバーはまだ構築されていないため、メモリを割り当てる必要があります。そのメモリ割り当て (およびデータの実際のコピー、ただしそれはリース コスト) をインターフェイスに移動できるため、呼び出し元が一時的なものを持っている場合、追加のメモリ割り当てなしで転送できます。

割り当ての場合、物事はもう少し複雑です。文字列の現在のサイズが新しい値を保持するのに十分な大きさである場合、割り当ては必要ありませんが、文字列が十分に大きくない場合は、再割り当てする必要があります。割り当てがインターフェイス (値渡しの引数) に移動された場合、不要な場合でも常に実行されます。割り当てが関数 (const 参照引数) 内で行われる場合、少数のケース (引数が現在のバッファーよりも大きい一時的なものである場合) では、そうでなければ回避できた可能性のある割り当てが行われます。

于 2013-09-06T14:21:58.733 に答える
0

次の利点があるため、メンバー初期化リストを使用して値を初期化することをお勧めします。

1) 割り当てバージョンは、デフォルトのコンストラクターを作成して mStr を初期化し、デフォルトで構築された値の上に新しい値を割り当てます。MIL を使用すると、リスト内の引数がコンストラクターの引数として使用されるため、この無駄な構成を回避できます。

2)クラスで列挙型を使用できる整数でない限り、定数変数を初期化する唯一の場所です。列挙型 T{v=2};

3) 参照を初期化する場所です。

これは私が提案するものです:

#include <iostream>
#include <string>

class A
{
   private:
      std::string mStr;

   public:
      A(std::string str):mStr(str){}

      //if you are using an older version of C++11, then use 
      //std::string &str instead
      inline const void setString(std::string str)
      {
         mStr = str;
      }

      const std::string getString() const
      {
         return mStr;
      }
};

int main()
{
   A a("this is a 1st test.");

   a.setString("this is a 2nd test.");

   std::cout<<a.getString()<<std::endl;
}

これを見てください: http://www.cplusplus.com/forum/articles/17820/

于 2013-09-06T14:24:54.520 に答える
0

この場合、引数を const 参照で渡す方がよいでしょう。理由: string はクラス型です。変更しないでください。任意の大きさにすることができます。

于 2013-09-06T13:32:34.850 に答える