7

私の現在の実装では、この構文で多くのコピーコンストラクターを使用しています

MyClass::Myclass(Myclass* my_class)

それは本当に(機能的に)違うのですか

MyClass::MyClass(const MyClass& my_class)

なぜ?

最初の解決策は真のコピーコンストラクターではないとアドバイスされました。ただし、変更を加えることは、かなり多くのリファクタリングを意味します。

ありがとう!!!

4

5 に答える 5

19

最初のものがコピーコンストラクターではなく、変換コンストラクターであるという意味で異なります。MyClass*aから。に変換しMyClassます。

定義上、コピーコンストラクターには次のいずれかの署名があります。

MyClass(MyClass& my_class)
MyClass(const MyClass& my_class)
//....
//combination of cv-qualifiers and other arguments that have default values

12.8。クラスオブジェクトのコピー

2)クラスXの非テンプレートコンストラクターは、最初のパラメーターがタイプX&、const X&、volatile X&、またはconst volatile X&であり、他のパラメーターがないか、他のすべてのパラメーターにデフォルトの引数がある場合、コピーコンストラクターです(8.3 .6).113)[例:X :: X(const X&)およびX :: X(X&、int = 1)はコピーコンストラクターです。

編集:あなたは2つを混同しているようです。

あなたが持っていると言う:

struct A
{
   A();
   A(A* other);
   A(const A& other);
};

A a;     //uses default constructor
A b(a);  //uses copy constructor
A c(&a); //uses conversion constructor

それらは一緒に異なる目的を果たします。

于 2012-10-02T10:54:10.380 に答える
8

最初のバージョンはコピーコンストラクタではありません。そのような単純な。これは単なる別のコンストラクターです。

クラスのコピーXコンストラクターには、署名(X &, ...)or(X const &, ...)またはor(X volatile &, ...)または(X const volatile &, ...)、が必要です。最初の引数以外のすべての引数は、存在する場合はデフォルト値を持ちます(テンプレートであってはなりません)。


とはいえ、ゼロのルールに違反している理由については、慎重に検討する必要があります。適切に設計されたクラスのほとんどは、ユーザー定義のコピーコンストラクタ、コピー代入演算子、またはデストラクタをまったく持た、代わりに十分に依存する必要があります。 -設計されたメンバー。現在のコンストラクターがポインターを受け取るという事実は、コードが次のようなものに対して正しく動作するかどうか疑問に思いますMyClass x = y;—チェックする価値があります。

于 2012-10-02T10:55:06.880 に答える
6

特定の言語コンストラクターは、コピーコンストラクターを必要とします。

  • 値渡し
  • 値で返す
  • コピースタイルの初期化(ただし、その場合、コピーは省略されることがよくあります)

言語がコピーを要求し、コピーコンストラクターを提供している場合は、それを使用できます(もちろん、cv-qualificationsがOKであると仮定します)。

コピーコンストラクターを提供していないため、代わりにコンパイラーによって生成されたコピーコンストラクターを取得します。これは、クラスで行うのが適切でない場合でも、各データメンバーをコピーすることで機能します。たとえば、not-a-copy-constructorが明示的にディープコピーを実行したり、リソースを割り当てたりする場合は、コンパイラによって生成されたコピーを抑制する必要があります。

コンパイラによって生成されたコピーがクラスで機能する場合、コピーではないコンストラクタはほとんど無害です。しかし、それは特に良い考えではないと思います。

void some_function(const MyClass &foo);

MyClass *ptr = new MyClass();
const MyClass *ptr2 = ptr;
some_function(ptr); // compiles, but copies *ptr and uses the copy
MyClass bar(ptr2);  // doesn't compile -- requires pointer-to-non-const

コンパイラによって生成されたコピーがクラスに適していない場合でも、必要な変更を行うために多くのリファクタリングを行う必要はありません。not-a-constructorが、引数が指すオブジェクトを実際に変更しないと仮定します。したがって、署名を修正した後、次のようになります。

MyClass::MyClass(const MyClass* my_class) {
    // maybe treat null pointer specially
    // do stuff here
}

必要なもの:

MyClass::MyClass(const MyClass& my_class) {
    do_stuff(my_class);
}

MyClass::MyClass(const MyClass* my_class) {
    // maybe treat null pointer specially
    do_stuff(*my_class);
}

MyClass::do_stuff(const MyClass& my_class) {
    // do stuff here
}

my_classまた、初期化子リストを古いコンストラクターから新しいコンストラクターにコピーし、新しいコンストラクターのポインターではないという事実に合わせて変更する必要があります。

古いコンストラクターを削除するには、それを使用するコードを編集する必要があるため、多くのリファクタリングが必要になる場合があります。ただし、デフォルトのコピーコンストラクターの問題を修正するために、古いコンストラクターを削除する必要はありません。

于 2012-10-02T11:21:10.467 に答える
2

最初の例はコピーコンストラクターではありません。これは、それを提供するときに、コンパイラーが、以下と同等の署名を持つデフォルトのコピーコンストラクターを提供することを意味します。

MyClass(const MyClass& my_class);

コンストラクターで何か特別なことをしていて、コンパイラーが提供するコピーコンストラクターがそのロジックに従わない場合は、コピーコンストラクターを実装するか、それを無効にする方法を見つける必要があります。

于 2012-10-02T10:57:39.707 に答える
2

変換コンストラクターの代わりにコピーコンストラクターを使用したいのはなぜですか?

MyClassコピーコンストラクターが有効であることを期待するコードにオブジェクトを与えると、問題が発生する可能性があります。

これはSTLコンテナの場合です。たとえば、を使用する場合、std::vector<MyClass>ベクトルはコピーコンストラクタを使用して再割り当てのために要素を移動できることに注意する必要があります。

コンパイラーによって提供されるデフォルトのコンストラクターは、浅いコピーを実行し、すべての属性のコピーコンストラクターを呼び出して、ポインターのような基本型の単純なコピーを作成します。何らかの形式のディープコピーが必要な場合は、のコピーコンストラクタを適切に書き直す必要があります。MyClass

于 2012-10-02T11:12:00.337 に答える