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

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
taketoshi
記事: 222
登録日時: 15年前
住所: 日本国

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

#1

投稿記事 by taketoshi » 14年前

違いが分からないので質問させてください。

サンプルはただの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;
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

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

#2

投稿記事 by softya(ソフト屋) » 14年前

すいません。
まったく同じプログラムに見えるのですが・・・。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taketoshi
記事: 222
登録日時: 15年前
住所: 日本国

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

#3

投稿記事 by taketoshi » 14年前

ごめんなさい、間違えてました

コード:

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

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

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

#4

投稿記事 by beatle » 14年前

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

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

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

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

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

#5

投稿記事 by softya(ソフト屋) » 14年前

newでインスタンスを生成している意味がありませんしdeleteもされてませんので問題有りプログラムです。
普通にクラスのインスタンスを生成したほうが安全でしょう。
一般関数が保持するインスタンスだと言うことなので、そういう意味でもstaticにnewを使わずに普通にインスタンス生成するのが一番だと思います。

ただ、最初のプログラムはstatic int hoge;で値を保持しているのでbeatleさんの言われるようにプロセスに1つしか変数が存在できません。
複数のインスタンスを生成してもだた1つのstatic int hoge;を共有することになります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taketoshi
記事: 222
登録日時: 15年前
住所: 日本国

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

#6

投稿記事 by taketoshi » 14年前

仕事が忙しくて返事が出来ませんでした。申し訳ありません。

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

コード:

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をつけて書き起こしてみたら
期待通りにダイアログのハンドルを保持し続けてくれているみたいです。

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

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

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

#7

投稿記事 by softya(ソフト屋) » 14年前

(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が無いとバグになります。それと同一ブロックが呼び出される度にインスタンスが生成されるのでメモリリークが累積する恐れがあります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taketoshi
記事: 222
登録日時: 15年前
住所: 日本国

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

#8

投稿記事 by taketoshi » 14年前

>softyaさん

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

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

閉鎖

“C言語何でも質問掲示板” へ戻る