ページ 11

STLのvectorの使い方について教えてください

Posted: 2013年6月09日(日) 10:03
by taketoshi
SRPGを制作している中で、キャラクターのインスタンスをvectorで管理しようと思っています。
クラスへのポインタを扱うvectorをCCreateForceクラスで宣言し、MyUnitクラスを格納したいです。

CCreateForce::AddUnit関数内でvectorコンテナに代入をしているのですがプログラムが強制終了してしまいます。
デバッカで追っかけたところ、 MyForce.push_back(new MyUnit(add)); vectorへの代入文で終了しているようです。

正しい使い方を教えてください。お願いします。

コード:

//////////////////////////////////////////////////////////////////////////
//
//							MyUnit
//説明:味方キャラクターを定義したクラス
//親:CCharcterBase
//////////////////////////////////////////////////////////////////////////
class MyUnit : public CCharcterBase{
private:
	UnitData ud;
	int posx,posy;//位置情報
	bool Alive;//生存フラグ
	bool Belong;//味方部隊加入フラグ
public:
	MyUnit();
	MyUnit(int unique);
	~MyUnit();
};

//////////////////////////////////////////////////////////////////////////
//
//							CCreateForce
//説明:味方キャラクターの部隊情報
//親:CCharcterBase
//////////////////////////////////////////////////////////////////////////
class CCreateForce{
private:
	static vector<MyUnit*> MyForce;//キャラクタのインスタンス//死亡時にインスタンスは破棄しないこと、死亡フラグを立てる
public:
	static int AddUnit(CMap *cm);//新規加入ユニットを調べて追加する
	int Updata();
	int Draw();
	CCreateForce();
	CCreateForce(CMap *cm);
	~CCreateForce();
};

//-----------------------------------------------------------------------------
// 名前 : AddUnit
// 引数 :	
// 戻り値:	正常終了	= TRUE
//			エラー		= FALSE
// 説明 :vectorコンテナに現在仲間になっている味方を追加する
//-----------------------------------------------------------------------------
int CCreateForce::AddUnit(CMap *cm){

	int add[5];
	//新規加入者を取得
	for(int i = 0;i < sizeof(add) / sizeof(add[0]);++i){
		add[i] = cm->mpdef.AddUnit[i];
	}

	//vector配列に追加する
	for(int i = 0;i < sizeof(add) / sizeof(add[0]);++i){
		if(add[i] != 1000){
			MyForce.push_back(new MyUnit(add[i]));/*ここでエラー発生、使い方をご指導ください*/
		}
	}

	return 0;
}


Re: STLのvectorの使い方について教えてください

Posted: 2013年6月09日(日) 10:13
by Suikaba
ぱっと見で原因がわからないのと、intをとるMyUnitのコンストラクタの定義が見えないのでよくわかりません。
もしかするとそこで落ちてる可能性もありますので、できれば MyUnit::MyUnit(int) の定義もお願いします。

Re: STLのvectorの使い方について教えてください

Posted: 2013年6月09日(日) 10:15
by beatle
使い方はパッと見たところ合っているような気がします。

CCreateForce::MyForceはstatic変数なので、どこかに実体定義があると思いますが、どんな感じになってますか?
Suikabaさんの指摘に加えて教えていただけたら嬉しいです。

Re: STLのvectorの使い方について教えてください

Posted: 2013年6月09日(日) 10:22
by taketoshi
Suikabaさん、beatleさんご返信ありがとうございます。

MyUnitコンストラクタの定義は以下です

コード:

//-----------------------------------------------------------------------------
//コンストラクタ 
//ユニーク番号を引数に取り、キャラクタを生成する
//-----------------------------------------------------------------------------
MyUnit::MyUnit(int unique){
	ud = lpMyUnit[unique];
}

//lpMyUnitは以下の構造体です雛形データとしてあらかじめ別関数で内容を設定してあります
//この構造体を動的に確保しているため、ポインタになっています
//-----------------------------------------------------------------------------
//UnitData構造体 
//説明:味方キャラクタの初期状態を設定した構造体
//-----------------------------------------------------------------------------
typedef struct{

	int UniqueNo;//キャラクタ固有番号
	string szName;//キャラクタネーム
	int nSex;//性別
	int FirstJob;//初期クラス番号
	int FirstLevel;//加入時初期レベル
	int Exp;//経験値
	int Param[8];//0 = 力:1 = 魔力:2 = 技:3 = 速さ
				 //4 = 幸運:5 = 守備力:6 = 魔法防御:7 = 移動力

	int WeponLevel[10];//0 = 剣:1 = 槍:2 = 斧:3 = 弓
					   //4 = 杖
					   //5 = 炎魔法:6 = 雷魔法:7 = 風魔法
					   //8 = 光魔法:9 = 闇魔法

	int FirstItem[6];//初期装備
	int *TipHandle;//キャラクタのチップ画像

}UnitData;

CCreateForce::MyForceの実態定義は以下です

コード:

//-----------------------------------------------------------------------------
//	クラス内のstatic変数宣言領域
//-----------------------------------------------------------------------------
vector<MyUnit*> CCreateForce::MyForce;//キャラクタのインスタンス//死亡時にインスタンスは破棄しないこと、死亡フラグを立てる
今平行してgoogleで調べているのですが、vectorにクラスを入れるとコピーコンストラクタなどが想定より多く動く?との記載をみつけ
ここがひっかかっているのかな?とにらんでいますが解決には至っていません。
http://isoparametric.hatenablog.com/ent ... 1260408984

Re: STLのvectorの使い方について教えてください

Posted: 2013年6月09日(日) 10:27
by beatle
vectorの要素はコピーコンストラクタでコピーできなければなりません。
MyUnitはコピーコンストラクタが実装されてないので、コンパイラにより暗黙で MyUnit(const MyUnit&) が実装されます。
暗黙で実装されたデフォルトコピーコンストラクタは、メンバを愚直に全部コピーします。
だから、メンバにポインタを持っていると、ポインタ値がコピーされます。
(2つのポインタが同じ領域を指すことになる)

一見、MyUnitはポインタを持っていないように見えますが、実は UnitData の中に TipHandle というポインタがあるので、そこは注意する必要があります。

ところで、MyUnitコンストラクタで使っている lpMyUnit がとても気になります。
添字オーバーとかしていませんか?

Re: STLのvectorの使い方について教えてください

Posted: 2013年6月09日(日) 10:29
by beatle
beatle さんが書きました:vectorの要素はコピーコンストラクタでコピーできなければなりません。
MyUnitはコピーコンストラクタが実装されてないので、コンパイラにより暗黙で MyUnit(const MyUnit&) が実装されます。
暗黙で実装されたデフォルトコピーコンストラクタは、メンバを愚直に全部コピーします。
だから、メンバにポインタを持っていると、ポインタ値がコピーされます。
(2つのポインタが同じ領域を指すことになる)

一見、MyUnitはポインタを持っていないように見えますが、実は UnitData の中に TipHandle というポインタがあるので、そこは注意する必要があります。
すみません。自分で書いておいてあれですが、MyForceは vector<MyUnit*> 型なので、MyUnit自体がコピー可能かどうかは関係ないですね。
コピー可能でなければならないのは MyUnit* 型で、これはポインタなので必然的にコピー可能です。

Re: STLのvectorの使い方について教えてください

Posted: 2013年6月09日(日) 10:40
by taketoshi
>>beatleさん

>ところで、MyUnitコンストラクタで使っている lpMyUnit がとても気になります。
>添字オーバーとかしていませんか?

printf関数を噛まして、1ステップ実行しながら調べてみたところ
MyUnitコンストラクタ内のlpMyUnitからUnitData udへコピーする箇所で落ちてました。

int uniqueを0にハードコートしても落ちてしまいます。
普通にMyUnitクラスをnewすることは可能なのですが、原因が掴めません。

コード:

MyUnit::MyUnit(int unique){
	ud = lpMyUnit[unique];//ここでxstringヘッダファイル?内でエラーを起こしている
	printf("");
}

GameProg.exe の 0x001e1c59 で初回の例外が発生しました: 0xC0000005: 場所 0x00000000 を読み込み中にアクセス違反が発生しました。
GameProg.exe の 0x774b15de でハンドルされていない例外が発生しました: 0xC0000005: 場所 0x00000000 を読み込み中にアクセス違反が発生しました。
プログラム '[15620] GameProg.exe: ネイティブ' はコード -1073741819 (0xc0000005) で終了しました。

Re: STLのvectorの使い方について教えてください

Posted: 2013年6月09日(日) 10:45
by taketoshi
ああぁ!すいません、凡ミスで解決しました。

xstringで落ちていたので、lpMyUnitを確認したところデータが全くロードされていませんでした。
lpMyUnitのロード→MyUnitクラスのインスタンス化とするべきところを
MyUnitのインスタンス化→lpMyUnitのロードという逆の順番になっていて落ちていました。

お二方アドバイスありがとうございました。解決とさせていただきます。