C++のvectorの使い方について教えてほしいです

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
doss

C++のvectorの使い方について教えてほしいです

#1

投稿記事 by doss » 10年前

お世話になります。また知識不足からなる疑問点で質問に来ました。
とりあえず疑問点に関連するであろうソースを載せていきます。
Title.h

コード:

#ifndef TITLE_H
#define TITLE_H

#include"Scene.h"
#include"Button.h"
#include"Label.h"

class TITLE : public SCENE{
private:
	BUTTON *StartButton;
	BUTTON *StageSelectButton;
	BUTTON *ConfigButton;
	BUTTON *EndButton;
	LABEL *TitleLabel;
	int Score;
public:
	//描画
	int Draw();
	TITLE();
	~TITLE();
};

#endif TITLE_H
Title.cpp

コード:

#include"Title.h"
#include"Scene.h"
#include"DxLib.h"
#include<vector>
TITLE::TITLE() : SCENE(){
	std::vector<POSITION*> Position;
	Position.push_back(&POSITION(0.0,0.0));
	Position.push_back(&POSITION(200.0,300.0));
	Position.push_back(&POSITION(200.0,400.0));
	Position.push_back(&POSITION(200.0,500.0));
	Position.push_back(&POSITION(200.0,600.0));
	Position.push_back(&POSITION(200.0,50.0));

	std::vector<IMAGE*> Image;
	Image.push_back(&IMAGE("BackGround.png",1,1));
	Image.push_back(&IMAGE("StartButton.png",1,1));
	Image.push_back(&IMAGE("ConfigButton.png",1,1));
	Image.push_back(&IMAGE("StageSelectButton.png",1,1));
	Image.push_back(&IMAGE("EndButton.png",1,1));
	Image.push_back(&IMAGE("TitleLabel.png",1,1));

	SOUNDEFFECT* sndef = new SOUNDEFFECT("ChangeButton.mp3",1);

	this->BackGround = new BACKGROUND(Image[0],Position[0]);
	this->StartButton = new BUTTON(Image[1],Position[1],sndef);
	this->ConfigButton = new BUTTON(Image[2],Position[2],sndef);
	this->StageSelectButton = new BUTTON(Image[3],Position[3],sndef);
	this->EndButton = new BUTTON(Image[4],Position[4],sndef);
	this->TitleLabel = new LABEL(Image[5],Position[5]);

	this->BackMusic = new SOUNDEFFECT("Title.mp3",1);
}
TITLE::~TITLE(){}
int TITLE::Draw(){
	std::vector<IMAGE*> Image;
	Image.push_back(this->StartButton->GetImage());


	std::vector<POSITION*> Position;
	Position.push_back(this->StartButton->GetPosition());
	Position.push_back(this->EndButton->GetPosition());

	DxLib::printfDx("pox : %lf , poy : %lf\n",Position[0]->GetX(),Position[0]->GetY());

	//背景画像の表示
	//タイトル画像の表示
	//始めるのボタンの表示
	//DxLib::DrawGraph( Position[0]->GetX() , Position[0]->GetY() , Image[0]->GetImage(0) , 1 );
	//ステージセレクトのボタンの表示
	//コンフィグのボタンの表示
	//終わりのボタンの表示
	return 0;
}
Button.cpp

コード:

#include"Button.h"
#include"DxLib.h"

SOUNDEFFECT *BUTTON::GetSoundEffect(){	return this->SoundEffect;	}
POSITION *BUTTON::GetPosition(){	return this->Position;	}
IMAGE *BUTTON::GetImage(){	return this->Image;	}
int BUTTON::Sound(){	return 0;	}
int BUTTON::GetChoose(){	return this->Choose;	}
int BUTTON::SetChoose( int choose ){	return this->Choose = choose;	}
BUTTON::BUTTON( IMAGE *image , POSITION* position , SOUNDEFFECT *soundeffect ){
	this->Choose = 0;
	IMAGE *img = new IMAGE("Frame.png",1,1);
	this->Frame = new FRAME(img,this->Position);
	this->Image = image;
	this->Position = position;
	this->SoundEffect = soundeffect;
}
BUTTON::BUTTON(){}
BUTTON::BUTTON( BUTTON &&button ){}
BUTTON::~BUTTON(){}
Button.h

コード:

#ifndef BUTTON_H
#define BUTTON_H

#include"Frame.h"
#include"SoundEffect.h"

class BUTTON{
private:
	SOUNDEFFECT *SoundEffect;
	IMAGE *Image;
	POSITION *Position;
	FRAME *Frame;
	int Choose;
public:
	int Sound();
	int GetChoose();
	int SetChoose( int choose );
	IMAGE *GetImage();
	POSITION *GetPosition();
	SOUNDEFFECT *GetSoundEffect();
	BUTTON( IMAGE *image , POSITION* position , SOUNDEFFECT *soundeffect );
	BUTTON();
	BUTTON( BUTTON &&button );
	~BUTTON();
};

#endif BUTTON_H
Frame.cpp

コード:

#include"Frame.h"

FRAME::FRAME( IMAGE *image , POSITION *position ){
	this->Position = position;
	this->Image = image;
}
FRAME::FRAME(){}
FRAME::FRAME( FRAME &&frame ){}
FRAME::~FRAME(){}
Frame.h

コード:

#ifndef FRAME_H
#define FRAME_H

#include"Image.h"
#include"Position.h"

class FRAME{
private:
	IMAGE *Image;
	POSITION *Position;
public:
	FRAME( IMAGE *image , POSITION *position );
	FRAME();
	FRAME( FRAME &&frame );
	~FRAME();
};

#endif FRAME_H
Image.cpp

コード:

#include"Image.h"
#include"DxLib.h"
#include<string>

int IMAGE::GetImage( int imagenumber ){
	return this->ImageData[imagenumber];
}
IMAGE::IMAGE( std::string filename , int numberx , int numbery ){
	int imagedata = DxLib::LoadGraph(filename.c_str());
	int *imagedatas = new int[numberx*numbery]; 
	DxLib::GetGraphSize(imagedata,&this->SizeX,&this->SizeY);
	DxLib::LoadDivGraph(filename.c_str(),numberx*numbery,numberx,numbery,this->SizeX/numberx,this->SizeY/numbery,imagedatas);
	for( int i=0; i<numberx*numbery; i++ )	this->ImageData.push_back(imagedatas[i]);
	delete[] imagedatas;
}
IMAGE::IMAGE(){}
IMAGE::IMAGE( IMAGE &&image ){}
IMAGE::~IMAGE(){}
Image.h

コード:

#ifndef IMAGE_H
#define IMAGE_H

#include<vector>

class IMAGE{
private:
	std::vector<int> ImageData;
	int SizeX;
	int SizeY;
	int ImageNumber;	//画像数
public:
	int GetImage( int imagenumber );
	IMAGE( std::string filename , int numbery , int numberx );
	IMAGE();
	IMAGE( IMAGE &&image );
	~IMAGE();
};

#endif IMAGE_H
上記のソースの疑問点はTitle.cppのDraw関数内の部分です。
そこで表示されるPositionやImageの値が0.0のままで変化がないのです。
頭の悪い質問ですがこの中に値を入れるにはどのような書き換えが必要なのでしょうか?
お願いします。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: C++のvectorの使い方について教えてほしいです

#2

投稿記事 by みけCAT » 10年前

・POSITIONの定義はどうなっていますか?
・printfDxに渡している書式文字列を"pox : %f , poy : %f\n"にしてみてください。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

doss

Re: C++のvectorの使い方について教えてほしいです

#3

投稿記事 by doss » 10年前

みけCATさん、こんにちは
POSITIONのソースをはり忘れていましたね、申し訳ないです。
Position.cpp

コード:

#include"Position.h"
#include"DxLib.h"

double POSITION::GetX(){
	return this->X;
}
double POSITION::GetY(){
	return this->Y;
}
POSITION::POSITION( double x , double y ){
	this->X = x;	this->Y = y;
}
POSITION::POSITION(){}
POSITION::POSITION( POSITION &&position ){}
POSITION::~POSITION(){}
Position.h

コード:

#ifndef POSITION_H
#define POSITION_H

class POSITION{
private:
	double X;
	double Y;
public:
	double GetX();
	double GetY();

	POSITION( double x , double y );
	POSITION();
	POSITION( POSITION &&position );
	~POSITION();
};

#endif POSITION_H
こちらになります。

%lf -> %f にしてもだめでした、、、

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: C++のvectorの使い方について教えてほしいです

#4

投稿記事 by みけCAT » 10年前

Title.cppの6~20行目でpush_backしているポインタは、おそらくすぐに消える一時オブジェクトのポインタであり、ゴミです。
このことは、以下のコードを実行するとわかります。
すでにデストラクタが呼び出されているオブジェクトのポインタが参照されていることがわかります。
入れた値が表示されているのは、多分たまたまです。

コード:

#include <cstdio>
#include <vector>

struct HOGE {
	int a;
	HOGE(int p=0):a(p) {
		printf("HOGE %p constructed\n", (void*)this);
	}
	HOGE(const HOGE& h):a(h.a) {
		printf("HOGE %p constructed by copy from %p\n", (void*)this,(void*)&h);
	}
	HOGE& operator=(const HOGE& h) {
		a=h.a;
		printf("HOGE %p assigned to the data of %p\n", (void*)this,(void*)&h);
		return *this;
	}
	~HOGE() {
		printf("HOGE %p destructed\n", (void*)this);
	}
};

void dump_vector(const std::vector<HOGE*>& v) {
	for(std::vector<HOGE*>::const_iterator it=v.begin();it!=v.end();it++) {
		printf("%d(%p) ",(*it)->a, (void*)*it);
	}
	putchar('\n');
}

int main(void) {
	std::vector<HOGE*> a;
	std::vector<HOGE*> b;
	a.push_back(&HOGE(1));
	a.push_back(&HOGE(2));
	a.push_back(&HOGE(3));
	a.push_back(&HOGE(4));
	a.push_back(&HOGE(5));

	b.push_back(&HOGE(11));
	b.push_back(&HOGE(22));
	b.push_back(&HOGE(33));
	b.push_back(&HOGE(44));
	b.push_back(&HOGE(55));

	dump_vector(a);
	dump_vector(b);
}

コード:

prog.cc: In function 'int main()':
prog.cc:32:24: warning: taking address of temporary [-fpermissive]
    a.push_back(&HOGE(1));
                       ^
(以下同じ内容の繰り返し)
という警告も出ました。
(コンパイルオプション-fpermissiveを付けないとエラーになりました)

きちんと有効なデータを指したポインタ、もしくはオブジェクトそのものを保持するようにしないといけません。
メモリリークにも気をつける必要があります。
自分がやったように、作成したオブジェクトをまとめて管理しておいて、
参照されなくなったら開放するという方法もありますが、難易度が高いです。
データをどのように保持すればよいか、考えてみてください。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: C++のvectorの使い方について教えてほしいです

#5

投稿記事 by みけCAT » 10年前

std::vectorにオブジェクトのポインタではなく、オブジェクトそのものをpush_backするのが楽だと思います。
この場合、意図しないシャローコピー(オブジェクト中のポインタが指しているデータをコピーせず、同じデータを指すコピー)にならないように、
ポインタを持つクラス(TITLE、BUTTON、FRAMEなど)のコピーコンストラクタを適切に定義してください。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

doss

Re: C++のvectorの使い方について教えてほしいです

#6

投稿記事 by doss » 10年前

みけCATさん、ありがたい返答ありがとうございます。
さっそくソースをこのように書き換えてためしてみましたが、やはり数値がすごいことになってしまいます。
Title.cpp

コード:

TITLE::TITLE() : SCENE(){
	std::vector<POSITION> Position;
	Position.push_back(POSITION(0.0,0.0));
	Position.push_back(POSITION(200.0,300.0));
	Position.push_back(POSITION(200.0,400.0));
	Position.push_back(POSITION(200.0,500.0));
	Position.push_back(POSITION(200.0,600.0));
	Position.push_back(POSITION(200.0,50.0));

	std::vector<IMAGE> Image;
	Image.push_back(IMAGE("BackGround.png",1,1));
	Image.push_back(IMAGE("StartButton.png",1,1));
	Image.push_back(IMAGE("ConfigButton.png",1,1));
	Image.push_back(IMAGE("StageSelectButton.png",1,1));
	Image.push_back(IMAGE("EndButton.png",1,1));
	Image.push_back(IMAGE("TitleLabel.png",1,1));

	SOUNDEFFECT *sndef = new SOUNDEFFECT("ChangeButton.mp3",1);

	this->BackGround = new BACKGROUND(&Image[0],&Position[0]);
	this->StartButton = new BUTTON(&Image[1],&Position[1],sndef);
	this->ConfigButton = new BUTTON(&Image[2],&Position[2],sndef);
	this->StageSelectButton = new BUTTON(&Image[3],&Position[3],sndef);
	this->EndButton = new BUTTON(&Image[4],&Position[4],sndef);
	this->TitleLabel = new LABEL(&Image[5],&Position[5]);

	
	DxLib::printfDx("pox : %lf , poy : %lf\n",Position[1].GetX(),Position[1].GetY());


	this->BackMusic = new SOUNDEFFECT("Title.mp3",1);
}
これはどこに問題があるのでしょうか、、、

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: C++のvectorの使い方について教えてほしいです

#7

投稿記事 by みけCAT » 10年前

コード:

#include <cstdio>
#include <vector>

class POSITION{
private:
    double X;
    double Y;
public:
    double GetX();
    double GetY();
 
    POSITION( double x , double y );
    POSITION();
    POSITION( POSITION &&position );
    ~POSITION();
};

double POSITION::GetX(){
    return this->X;
}
double POSITION::GetY(){
    return this->Y;
}
POSITION::POSITION( double x , double y ){
    this->X = x;    this->Y = y;
    printf("position %p constructed with parameter %f,%f\n",(void*)this,x,y);
}
POSITION::POSITION(){
    printf("position %p constructed\n",(void*)this);
}
POSITION::POSITION( POSITION &&position ){
    printf("position(%p) = %f,%f  this(%p) = %f,%f\n",(void*)&position,position.X,position.Y,(void*)this,X,Y);
}
POSITION::~POSITION(){
    printf("position %p destructed\n",(void*)this);
}

int main(void) {
    std::vector<POSITION> Position;
    Position.push_back(POSITION(0.0,0.0));
    Position.push_back(POSITION(200.0,300.0));
    Position.push_back(POSITION(200.0,400.0));
    Position.push_back(POSITION(200.0,500.0));
    Position.push_back(POSITION(200.0,600.0));
    Position.push_back(POSITION(200.0,50.0));

    printf("pox : %f , poy : %f po : %p\n",Position[1].GetX(),Position[1].GetY(),(void*)&Position[1]);
    return 0;
}
というコードを実行するとわかるように、POSITIONに空のムーブコンストラクタがあるせいで、値が引き継がれていません。
POSITIONのムーブコンストラクタ

コード:

POSITION( POSITION &&position );
などを適切に実装してください。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

doss

Re: C++のvectorの使い方について教えてほしいです

#8

投稿記事 by doss » 10年前

みけCATさん!進展がありました!!おっしゃっていた通りムーブコンストラクタの書き換えを行ったところ、数値がうまく入りました!!
Position.cpp

コード:

#include"Position.h"
#include"DxLib.h"

double POSITION::GetX(){
	return this->X;
}
double POSITION::GetY(){
	return this->Y;
}
POSITION::POSITION( double x , double y ){
	this->X = x;	this->Y = y;
}
POSITION::POSITION(){}
POSITION::POSITION( POSITION &&position ){
	this->X = position.X;
	this->Y = position.Y;
}
POSITION::~POSITION(){}
しかし、今度は初期化のちの数値がおかしくなってしまうのです。
Title.cpp

コード:

#include"Title.h"
#include"Scene.h"
#include"DxLib.h"
#include<vector>
TITLE::TITLE() : SCENE(){
	std::vector<POSITION> Position;
	Position.push_back(POSITION(0.0,0.0));
	Position.push_back(POSITION(200.0,300.0));
	Position.push_back(POSITION(200.0,400.0));
	Position.push_back(POSITION(200.0,500.0));
	Position.push_back(POSITION(200.0,600.0));
	Position.push_back(POSITION(200.0,50.0));

	std::vector<IMAGE> Image;
	Image.push_back(IMAGE("BackGround.png",1,1));
	Image.push_back(IMAGE("StartButton.png",1,1));
	Image.push_back(IMAGE("ConfigButton.png",1,1));
	Image.push_back(IMAGE("StageSelectButton.png",1,1));
	Image.push_back(IMAGE("EndButton.png",1,1));
	Image.push_back(IMAGE("TitleLabel.png",1,1));

	SOUNDEFFECT *sndef = new SOUNDEFFECT("ChangeButton.mp3",1);

	this->BackGround = new BACKGROUND(&Image[0],&Position[0]);
	this->StartButton = new BUTTON(&Image[1],&Position[1],sndef);
	this->ConfigButton = new BUTTON(&Image[2],&Position[2],sndef);
	this->StageSelectButton = new BUTTON(&Image[3],&Position[3],sndef);
	this->EndButton = new BUTTON(&Image[4],&Position[4],sndef);
	this->TitleLabel = new LABEL(&Image[5],&Position[5]);

	
	DxLib::printfDx("pox : %lf , poy : %lf\n",Position[1].GetX(),Position[1].GetY());

	POSITION* p= this->StartButton->GetPosition();

	DxLib::printfDx("pox : %lf , poy : %lf\n",p->GetX(),p->GetY());

	this->BackMusic = new SOUNDEFFECT("Title.mp3",1);
}
TITLE::~TITLE(){}
int TITLE::Draw(){
	std::vector<IMAGE> Image;
	Image.push_back(*this->StartButton->GetImage());


	std::vector<POSITION> Position;
	Position.push_back(*this->StartButton->GetPosition());
	Position.push_back(*this->EndButton->GetPosition());

	POSITION* p = this->StartButton->GetPosition();

	DxLib::printfDx("pox : %lf , poy : %lf\n",p->GetX(),p->GetY());
	DxLib::printfDx("pox : %lf , poy : %lf\n",Position[0].GetX(),Position[0].GetY());

	//背景画像の表示
	//タイトル画像の表示
	//始めるのボタンの表示
	//DxLib::DrawGraph( Position[0]->GetX() , Position[0]->GetY() , Image[0]->GetImage(0) , 1 );
	//ステージセレクトのボタンの表示
	//コンフィグのボタンの表示
	//終わりのボタンの表示
	return 0;
}
何度も質問してしまって申し訳ありません。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: C++のvectorの使い方について教えてほしいです

#9

投稿記事 by みけCAT » 10年前

TITLE::TITLE()のPositionのデータは、この関数を抜けた時点で破棄されます。
当然、このPositionが保持しているデータ(要素)へのポインタも無効になります。
Imageについても同様です。
BACKGROUNDクラスやBUTTONクラス、LABELクラスに、
IMAGEクラスやPOSITIONクラスのポインタではなくインスタンスそのものを持たせることを検討してください。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

doss

Re: C++のvectorの使い方について教えてほしいです

#10

投稿記事 by doss » 10年前

みけCATさん!ありがとうございます!!無事解決に至りました!!
今後またどうしても自分で解決できない問題があればまたお願いするかもしれません。どうもありがとうございました。

閉鎖

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