ページ 11

この宣言の違いは何になりますか?

Posted: 2012年4月15日(日) 21:44
by taketoshi
違いが分からないので質問させてください。

サンプルはただのmain関数に記述していますが、本来ならばウインドウプロシージャに記述し
一度スコープを抜けても、変数内のint hogeの値を保持する目的で書いています。

どちらもクラス内変数のhogeはスコープを抜けても保持されるような気がするのですが・・・・。
ちょっと自分の中でもあいまいです。

それぞれメモリ上はどの様な違いになるのかご指導いただけると助かります。



以下はただ単に、クラス内の変数hogeをstaticにして保持しようとしています。

コード:


class hoge{
private:
	static int hoge;
public:
	int show();
};

int _tmain(int argc, _TCHAR* argv[])
{

	hoge *hg = new hoge();

	hg->show();

	return 0;
}

以下はクラスへのポインタをstaticにしてクラス全体の変数を保持しようとしています。

コード:

class hoge{
private:
	static int hoge;
public:
	int show();
};

int _tmain(int argc, _TCHAR* argv[])
{

	hoge *hg = new hoge();

	hg->show();

	return 0;
}

Re: この宣言の違いは何になりますか?

Posted: 2012年4月15日(日) 23:32
by softya(ソフト屋)
すいません。
まったく同じプログラムに見えるのですが・・・。

Re: この宣言の違いは何になりますか?

Posted: 2012年4月16日(月) 07:24
by taketoshi
ごめんなさい、間違えてました

コード:

class hoge{
private:
    int hoge;
public:
    int show();
};
 
int _tmain(int argc, _TCHAR* argv[])
{
 
    static hoge *hg = new hoge();
 
    hg->show();
 
    return 0;
} 
こちらです。

Re: この宣言の違いは何になりますか?

Posted: 2012年4月16日(月) 08:01
by beatle
前者のhoge *hgバージョンでは、_tmain関数が呼び出されるたびにnew hoge();が実行されてポインタ変数hgが初期化されます。
後者のstatic hoge *hgバージョンでは、_tmain関数が最初に呼ばれたときにだけnew hoge();が実行されてポインタ変数hgが初期化されます。

しかし、int型変数hoge::hogeはstaticメンバなので、いくらnew hoge();などによりhogeのインスタンスを生成しても、hoge::hogeはプロセス内で1つしか存在しません。

期待した結果と想像した結果が異なるような具体的なプログラムはありますか?具体的なソースコードを提示していただいて「ここが想像と違うのですが」と質問していただければ、もっと答えやすいとおもいます。

Re: この宣言の違いは何になりますか?

Posted: 2012年4月16日(月) 08:32
by softya(ソフト屋)
newでインスタンスを生成している意味がありませんしdeleteもされてませんので問題有りプログラムです。
普通にクラスのインスタンスを生成したほうが安全でしょう。
一般関数が保持するインスタンスだと言うことなので、そういう意味でもstaticにnewを使わずに普通にインスタンス生成するのが一番だと思います。

ただ、最初のプログラムはstatic int hoge;で値を保持しているのでbeatleさんの言われるようにプロセスに1つしか変数が存在できません。
複数のインスタンスを生成してもだた1つのstatic int hoge;を共有することになります。

Re: この宣言の違いは何になりますか?

Posted: 2012年4月22日(日) 16:30
by taketoshi
仕事が忙しくて返事が出来ませんでした。申し訳ありません。

ダイアログ等、ハンドルの類を後から使いまわすような処理をしたくて
今回どの様に記述すればいいのか悩んでおりました。

コード:

class Dialog{
protected:
	static HWND hDlg;//ここのダイアログのハンドルは保持され続けるのか?
public:
	int CreateDialogBox(HWND);
};

int Dialog::CreateDialogBox(HWND hParent){

	HINSTANCE hInst = (HINSTANCE)GetWindowLongPtr(hParent,GWLP_HINSTANCE);
	//ダイアログの作成
	hDlg = CreateDialog(hInst,
		MAKEINTRESOURCE(IDD_DIALOG1),
		hParent,
		NULL);

	if(hDlg == NULL){
		MSE("ダイアログ作成エラー");
		return -1;
	}


	return 0;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
//関数名			:メインウインドウプロシージャ
//機能				:
//引数				:
//戻り値			:
/////////////////////////////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK CMainWindow:: MainWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
	
	static Dialog CD;//クラスの宣言

	switch(msg)
	{
	case WM_CREATE:
		CD.CreateDialogBox(hWnd);//メインウインドウ作成と同時にダイアログを作ってそのハンドルを保持し続ける
		break;
	case WM_DESTROY:
		{
			PostQuitMessage(0);
			break;
		}
	default:
		return (DefWindowProc(hWnd,msg,wParam,lParam));
	}
	return 0;
}

迷っていた点は整理してみました。

コード:


Dialog CD;//普通にクラスを変数として宣言
static Dialog CD//クラス自体をstatic変数として宣言

Dialog *CD = new Dialog();//ポインタ変数として宣言してnewする
static Dialog *CD = new Dialog();//staticなポインタ変数として宣言する

結果は一緒だと考えているのですが、上記四つの宣言の使い分け方がわからない。


ただ、クラス内部の変数(今回はハンドル)も保持したかったので、お二方が仰るように、
クラス自体をstatic宣言して普通にインスタンスを生成する2番目が適当のようですね

ポインタ変数についてはDeleteすることを前提で書いております。

ダイアログはひとつしか生成しないのでクラス内部自体にもstaticをつけて書き起こしてみたら
期待通りにダイアログのハンドルを保持し続けてくれているみたいです。

一週間ほどほったらかしで申し訳なかったです。
一応の解決とさせていただきます。

Re: この宣言の違いは何になりますか?

Posted: 2012年4月22日(日) 16:59
by softya(ソフト屋)
(1)Dialog CD;//普通にクラスを変数として宣言
(2)static Dialog CD//クラス自体をstatic変数として宣言
(3)Dialog *CD = new Dialog();//ポインタ変数として宣言してnewする
(4)static Dialog *CD = new Dialog();//staticなポインタ変数として宣言する

(2)と(4)は、プロセス起動時にインスタンスが生成されます。
(4)はdeleteを呼び忘れるとメモリリークとデストラクタの呼び出しがありませんが何処でdeleteするのか結構悩みます。
(1)と(3)はブロック内で変数生成時にインスタンスが生成されます。
(3)は(4)と同様にdeleteが無いとバグになります。それと同一ブロックが呼び出される度にインスタンスが生成されるのでメモリリークが累積する恐れがあります。

Re: この宣言の違いは何になりますか?

Posted: 2012年4月26日(木) 21:23
by taketoshi
>softyaさん

解りやすいご説明ありがとうございます。
new演算子で生成する場合は気を付けて書かないと知らない間にメモリリークを作っていることが多くなりそうです。

ご教授ありがとうございます。