2017-03-21 6 views
5

次のコンパイルはなぜですか?C++クラスのコンパイル

class A{ 
    A(){ 
     A* a = new A() ; 
    } 
} ; 

同じ理由で失敗するはずはありませんか?

class A{ 
    A obj; 
} ; 
+2

おそらく、最初にバリエーション 'class A {A {} {A obj;}} ;; –

+0

をコンパイラが実行することができるかもしれません。それが間違っていることを知っているにもかかわらず、それを行う方法を言うのは簡単です。 (私のコンパイラは、少なくとも警告を出す)。しかし、それはあなたがAを持っていると言うときにも始める方法を知らないA. A –

答えて

4
class A{ 
    A obj; 
} ; 

AのサイズはAに基づいているため、再帰的な爆弾です。明らかにそれは許されない。 Aはどれくらい大きいか分かりません。これはコンパイル時に捕らえやすい。

class A{ 
    A(){ 
     A* a = new A() ; 
    } 
} ; 

まだ再帰的な爆弾ですが、実行時に爆発して構文エラーではなく論理エラーになります。コンパイラが警告を発することがあります。

ここで秘密はクラスで定義された関数は、インライン関数のマジック([dcl.fct.spec]ポイント3を介して、していることであるが、下の点4であると思われる[dcl.inline]より最近の規格のドラフトでは)、クラスが他のコードで使用されるときに定義された後にコンパイルされます(または、関数が決して使用されない場合は、MMが以下を指摘するため)。

関数はコンパイルされる前にクラス定義の外に移動されるので、コンパイル時にはAのサイズがわかりますので、安全に構築できます。

A* aは単なるポインタです。サイズはすぐに焼かれ、特別な要件はありません。あなたは無限のストレージをこのように宣言しているため

+1

また、プログラムはAインスタンスを作成しないかもしれないので、コンパイラはクラス定義に基づいて拒否できません –

+0

再帰コンストラクタは確かに再帰的な爆弾が、それは一般的に法的措置です。それを検出するにはダイナミックアナライザが必要です。最初のケースは単に無限の記憶域の不正な定義です – Swift

1

宣言

class A{ 
    A obj; 
} ; 

は違法です。ただし、 には、独自のクラスの静的フィールドまたは非静的な基本クラスが含まれていることには注意してください。

class A{ 
    A(){ 
    A* a = new A(); 
    } 
}; 

よう

class A { 
public: 
    static A a; 
}; 

A A::a = A(); 

class B : A { 
    A obj; 
} 

物事は可能であり、どのような方法の中で宣言され、異なるストレージです。言語規則では合法ですが、意味的には間違っています。そのようなコンストラクタを呼び出すと、無限の再帰が発生します。

関連する問題