5

スニペット 1:

#include<iostream>
using namespace std;

class C{
public:
    C(){}
    C(const C& c){
        cout<<"const copy constructor called"<<endl;
    }
};
int main(){
    C c1;
    C c2 = c1;
    return 0;
}

output : const コピーコンストラクターが呼び出されました


スニペット 2:

#include<iostream>
using namespace std;

class C{
public:
    C(){}
    C(const C& c){
        cout<<"const copy constructor called"<<endl;
    }
    C(C& c){
        cout<<"non-const copy constructor called.\t "<<endl;
    }
};
int main(){
    C c1;
    C c2 = c1;
    return 0;
}

output : 非 const コピー コンストラクターが呼び出されました


スニペット 3:

#include<iostream>
using namespace std;

class C{
public:
    C(){}
    C(const C& c){
        cout<<"const copy constructor called"<<endl;
    }
    C(C c){
        cout<<"non-const copy constructor called.\t "<<endl;
    }
};
int main(){
    C c1;
    C c2 = c1;
    return 0;
}

出力: エラー: コピー コンストラクターは最初の引数を参照渡しする必要があります


私はとても混乱しています:

  1. スニペット 2 の場合、ここの非 const コピー コンストラクターが有効なのはなぜですか? const ではなく、非 const コピー コンストラクターが呼び出された理由。
  2. スニペット 3 については、無限再帰を避けるために、コピー コンストラクターが const 参照を使用する必要があることを知っています。しかし、クラス C には がありC(const C& c)C(C c)無限再帰は発生しません。なぜそれでも機能しないのでしょうか?
4

2 に答える 2

8

スニペット 1 : const T&. 幸せな世界。

スニペット 2 :

あなたが効果的に行ったことは、コピー コンストラクターをオーバーロードすることです。1 つは参照を受け取り、もう 1 つT&は定数参照を受け取りますconst T&

注意: タイプT &orの必須引数を 1 つ持つクラス T のコンストラクターconst T &(さらに、デフォルトの引数を持つこともできます) は、コピー コンストラクターです。

したがって、コンパイラにとっては、オーバーロードの解決に最適なものを見つけることになります。それは次のように行われます。

次の場合、標準変換シーケンス S1 は、標準変換シーケンス S2 よりも優れた変換シーケンスです。

  • ....
  • S1 と S2 は参照バインディング (8.5.3) であり、参照が参照する型はトップレベルの cv 修飾子を除いて同じ型であり、S2 によって初期化された参照が参照する型はより cv 修飾されています。 S1 によって初期化された参照が参照する型。

だから書いている

C c1;
C c2 = c1;

非 const コピー コンストラクターの方が適しているため、非 const コピー コンストラクターを呼び出しますが、

書き込み、

const C c1;
C c2 = c1;

const を使用したコピー コンストラクターが実行可能な唯一の一致であるため、const コピー コンストラクターを呼び出します (確認できます)。

スニペット 3 は、コンパイラにとって明らかに間違っています。

C(C c){
        cout<<"non-const copy constructor called.\t "<<endl;
    }

署名付きのメソッドを持つことはできませんC(C c)。コンパイラは、コピー コンストラクターを書き込もうとして、書き損じていると判断し&、エラーを報告します。それを削除すると、正常に動作します。

@非常に正当な理由がない限り、コピー コンストラクターには絶対に使用しないでください。C(C& c)constコピー元のオブジェクトを変更してもあまり意味がないため、スキップしないでください。

于 2016-02-22T06:00:13.830 に答える