関数内に宣言した変数とポインタとnewとmallocとコンストラクタとデストラクタについて

Javaの参照型はnewした時にその実体が生成されるわけだけど、C++はどうなってるのかテストしてみた。
テストは以下の4パターンで、main関数内に明示的なブロックを作ってその中に宣言しているので、スタックに確保されるものはブロックの終了で寿命が終わるハズ。
ブロック内で Hoge クラスのメンバ関数 func を呼んでいるがこける場合もある。
こけるものは func を呼ばないパターンを追加している。

条件

  • パターン
    • 値の場合
    • ポインタの場合
    • ポインタをnewした場合
    • ポインタをmallocした場合
  • コード
class Hoge{
public:
	Hoge(void){ printf("Hoge Constructor\n"); };	//コンストラクタ
	~Hoge(void){ printf("Hoge Destructor\n"); };	//デストラクタ
	void func(void){ printf("Hoge func\n"); };		//テスト関数
};

int main(void){
	printf("Start Block\n");
	//明示的なブロック	
	{
		//この中身を変えていくよー
	}
	printf("End Block\n");
	
	return 0;
};

結果

条件 ブロックの中身 実行結果
値の場合 Hoge hoge;
printf("Create Hoge\n");
hoge.func();
Start Block
Hoge Constructor
Create Hoge
Hoge func
Hoge Destructor
End Block
ポインタの場合 1 Hog*e hoge;
printf("Create Hoge\n");
hoge->func();
Start Block
Create Hoge
//エラー
ポインタの場合 2 Hog*e hoge;
printf("Create Hoge\n");
Start Block
Create Hoge
End Block
ポインタをnewした場合 Hoge* hoge = new Hoge();
printf("Create Hoge\n");
hoge->func();
Start Block
Hoge Constructor
Create Hoge
Hoge func
End Block
ポインタをmallocした場合 Hoge* hoge = (Hoge*)malloc(sizeof(Hoge));
printf("Create Hoge\n");
hoge->func();
Start Block
Create Hoge
Hoge func
End Block
条件 宣言時にコンストラクタを ブロック終了時にデストラクタを
値の場合 通る 通る
ポインタの場合 通らない 通らない
ポインタをnewした場合 通る 通らない
ポインタをmallocした場合 通らない 通らない
  • 値の場合

宣言時にコンストラクタを通り、ブロックを抜ける時にデストラクタが動く。
スタックに確保されていることがわかる。
宣言しただけではnullJavaの感覚で使うとまずいので注意。

  • ポインタの場合

コンストラクタが呼ばれておらず、func呼び出しでエラー。
アドレスが(スタックに?)確保されているだけなので実体は存在していない。
(ブロックの終了とともにアドレスは解放されてる?)

  • ポインタをnewした場合

new時にコンストラクタが呼び出されるがブロックを抜けてもデストラクタを通らない。
ヒープに確保されていることがわかる。
ちゃんとdeleteしないとリークする。
(アドレスはスタックに、実体はヒープにあるのでブロック終了前に開放しないとメモリリークする?)

  • ポインタをmallocした場合

コンストラクタもデストラクタも通らない。でも実体はあるんで作った後で初期化、使い終わったらfreeしないとだめ。
(アドレスはスタックに、実体はヒープにあるのでブロック終了前に開放しないとメモリリークする?)



結局デストラクタを勝手に呼んでくれる値の宣言がすごくいいんだけどなんか怖い。
C++ならnewでいいけどmallocはより低レベルで作業できそう。