2

次のような構文を探しています。

class Hugo
{
    Hugo();
    explicit Hugo( const Hugo& hugo );

    Hugo GetRandomHugo()
    {
        Hugo hugo;
        hugo.value = rand();
                                  // this would fail:
                                  //    return hugo;

        return Hugo(hugo);        // explicit copy!!
    }
};

言い換えれば、コピーコンストラクターが明示的であっても、メソッドがコピーを返すことができるように、明示的なコピー構文を探しています。

GCC 4.4.5 を使用しています。

どうもありがとう、

チャーリー

4

3 に答える 3

5

できません: 値による戻り値は暗黙のコピー構築です。ここで、戻り値は、明示的にコピー構築された一時的なものを暗黙的にコピーしようとします。

8.5/12 から:

引数の受け渡し、関数 return、例外のスロー (15.1)、例外の処理 (15.3)、および中括弧で囲まれた初期化子リスト (8.5.1) で発生する初期化は、コピー初期化と呼ばれ、次の形式と同等です。

T x = a;

于 2010-11-26T13:23:36.130 に答える
3

HugoCopy次のような明示的なクラスを使用することで、これを回避できます。

class HugoCopy;
class Hugo {
public:
    Hugo() { ... }  
    Hugo(HugoCopy const&);
    explicit Hugo(Hugo const&) { ... }
};

struct HugoCopy { 
    HugoCopy(Hugo const& hugo) 
      :hugo(hugo)
    { }

    Hugo const& hugo;
};

Hugo::Hugo(HugoCopy const&) { ... }

現在、次のセマンティクスが適用されます

Hugo a;
Hugo b = a; // forbidden
Hugo c(a); // allowed
Hugo d = HugoCopy(a); // allowed

Hugo f() {
  Hugo a;
  return a; // forbidden
  return HugoCopy(a); // allowed
}

または、変換関数を使用できます

class Hugo {
public:
    Hugo() { ... }  
    explicit Hugo(Hugo const&) { ... }
};

struct HugoCopy { 
    HugoCopy(Hugo const& hugo) 
      :hugo(hugo)
    { }
    operator Hugo const&() { return hugo; }

private:
    Hugo const& hugo;
};

これは、C++ 言語の微妙な部分に依存しています。したがって、これを使用すると、自分が何をしているのか、またはしていないのかがわかります。最初に HugoCopy の変換関数 (または最初のケースでは のコンストラクター) を呼び出して/Hugoを取得し、次にそれを指示します。そのオブジェクトで宛先オブジェクトを初期化します。GCC はこのコードを好みませんが、Clang と Comeau/EDG は上記のセマンティクスに従って受け入れます。HugoHugo const&HugoHugo

于 2010-11-26T13:45:28.807 に答える
1
return Hugo(hugo); 

これは、戻るに追加のコピーを 1 つ作成するだけです。次に、実際の return ステートメントがそのコピーを取得し、再度コピーします。コピー コンストラクターの全体的なポイントは、私たちまたはコンパイラーがオブジェクトのコピーを必要とするときはいつでも、暗黙的に使用できるということです。

明示的な構文が必要な場合は、Clone()またはCopy()関数をクラスに追加するだけで済みますが、コピー コンストラクターを置き換えることはできません。

コンパイラがオブジェクトをコピーする必要があるたびに (たとえば、関数パラメーターとして値で渡すとき、または関数から返すとき)、オブジェクトのコピーを作成する必要があります。呼び出し元と呼び出し先の間の「遷移」コードが表示されないため、コンパイラでこれを行う方法はありません。呼び出された関数の内部または外部にオブジェクトをコピーできますが、呼び出し先の本体から呼び出し元にコピーする方法はありません。これを行うことができるのはコンパイラだけです。そのためには、オブジェクトを自由にコピーできる必要があります。これは、コピー コンストラクタを介して行われます。

于 2010-11-26T13:42:32.533 に答える