vectorへのオブジェクト格納 – プログラミング – Home

vectorへのオブジェクト格納
 
通知
すべてクリア

[解決済] vectorへのオブジェクト格納

固定ページ 1 / 2

Baby Chicken
 Baby Chicken
(@Baby Chicken)
ゲスト
結合: 16年前
投稿: 45
Topic starter  

皆様方ご無沙汰しております。初歩的な質問で申し訳ありません。
Vista-Ultimate, VC++2008です vectorでオブジェクトを格納するのに下記のようなのを
書きました。
#include <iostream>
#include <vector>
using namespace std;

class A {
static int i;
int _i;
public:
A() {
cout << i << is born.\n;
_i = i++;
}
~A() {cout << A is deletinng.\n;}
void print() {cout << _i*_i << endl;}
};
int A::i = 0;

int main() {
vector <A*> groupA;
vector <A*>::iterator it;
for (int i=0; i<10; ++i) {
groupA.push_back(new A());
}
for (it = groupA.begin(); it != groupA.end(); ++it) {
(*it)->print();
}

char ch;
cin >> ch;
return 0;
}

質問は
(1)実行すると、Aのdestructorが呼ばれていないようですが、vectorに格納する場合に
は、
        A *p = new A();
groupA.push_back(p);
delete p;
のように分けて書かないといけないのでしょうか? 
(2)VC++でメモリーリークを検出するのにはどのようにすれば良いのでしょうか?
ご指導宜しくお願いします。


引用未解決
トピックタグ
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

まずそもそも vector (に限らず STL コンテナ) にポインタ値を入れるという設計が
あまりよくない (多態が必要な場合を除く) ので、その辺から再検討。

提示 (1) は
A* p=new A;
A* q=p;
delete p;
と同じことをやっているわけで delete p; の後はもう q を使うことができない。

(2) は、そもそもメモリーリークって何を意図してる?というあたりが明確でないので
答えにくいかな。

# 提示例 class A はバグっているというか、意味がよくわからないのでパスね


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 21年前
投稿: 600
 

> (1)実行すると、Aのdestructorが呼ばれていないようですが

呼ばれるワケがないので、mainの最後で明示的にdeleteします。

for (vector <A*>::iterator it = groupA.begin(); it != groupA.end(); ++it) {
delete *it;
}

C++0X準拠(VC++2010)になれば vector<shared_ptr<A>> でしょね。


返信引用
Baby Chicken
 Baby Chicken
(@Baby Chicken)
ゲスト
結合: 16年前
投稿: 45
Topic starter  

皆様方ご教示ありがとうございます。感謝しています。

tetrapod様
STLコンテナにポインタを入れるのは良くない、というのは何となく分かっていましたが、
そうなのですね。ありがとうございます。class Aはただのdummyです
メモリーリークの検出については、以前VC++で別のもう少しきちんとしたプログラム
(bitmapを用いたりするもの)を書いた時、debug modeで走らせたところ、最後にdebug
screenに memory leak was detectedと表示され、ポインタの解放忘れに気付いたのです
が、今回のものでは全く何も表示されず、プログラムが正しいように終了したからです。質
問が明確でなく申し訳ありません。

επιστημη様
やはり呼ばれる訳無いのですね。何となくvectorに期待していましたので・・・ そうです
ね、お示しされましたようにもう一度iteratorを使ってdeleteすれば良いのですね、こんな
ことも分からないなんて本当に馬鹿でした。お手を煩わせて申し訳ありませんでした。


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

回答ではありませんが、一般に配列クラスに格納している
要素がnewしたオブジェクトであることが保障されている場合、
それ専用に派生させた配列クラスのデストラクタで全ての
配列要素ををdeleteするってのは常用してます。
以降、この配列クラスから派生させたクラスの要素を削除する
コードは不要になるので楽チン。
ただし、newしたオブジェクトのポインタの「コピー」の配列は
削除しちゃいけない場面が想定できるので注意が必要ですが(vv;)。


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 21年前
投稿: 600
 

↓VC9(2008)ならさっくり動きます。お試しあれ。

#include <iostream>
#include <vector>
#include <memory>

using namespace std;
namespace std { using namespace std::tr1; }

class A {
static int i;
int _i;
public:
A() {
cout << i << is born.\n;
_i = i++;
}
~A() {cout << A is deletinng.\n;}
void print() {cout << _i*_i << endl;}
};

int A::i = 0;

int main() {
vector<shared_ptr<A>> groupA;
for (int i=0; i<10; ++i) {
groupA.push_back(shared_ptr<A>(new A()));
}
for (vector<shared_ptr<A>>::iterator it = groupA.begin(); it != groupA.end
(); ++it) {
(*it)->print();
}
}


返信引用
Baby Chicken
 Baby Chicken
(@Baby Chicken)
ゲスト
結合: 16年前
投稿: 45
Topic starter  

仲澤@失業者様
そうか、配列クラスを作ってそこのdestructorの中でdeleteするというのも(作るのは難し
そうですが)なかなか魅力的な気がします。今度挑戦してみます。

επιστημη様
shared_prtを用いてdeleteせずに済ます方法ご教授ありがとうございます。


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

> そうか、配列クラスを作ってそこのdestructorの中でdeleteするというのも(作るのは
難し
> そうですが)なかなか魅力的な気がします。今度挑戦してみます。

そんなに難しくないですよ。・・・テンプレート使えば。
stlはうっとおしいので、MFCのCArryから派生させると

template< typename T >
class ARY_with_AutoDel
: public CArray< T*>
{
private: BOOL m_AutoDel; // 自動削除
public:
ARY_with_AutoDel() : CArray< T*>(){
m_AutoDel = TRUE;
}
public:
virtual ~ARY_with_AutoDel(){ Destroy();}
void AutoDelete_Set( BOOL ex_flg){ m_AutoDel=ex_flg;}
void Destroy(){
if( FALSE == m_AutoDel){
RemoveAll();
return;
}
int num = int( this->GetCount()); // 要素数
T* t;
for( int i = num - 1 ; i>= 0 ; i--){
t = ( *this)[ i];
if( t) delete t;
( *this)[ i] = NULL;
}
RemoveAll();
}
};

class HOGE{
public:HOGE(){}
virtual ~HOGE(){} // virtualである必要がある
};
だったとき、HOGEの自動削除配列は

typedef ARY_with_AutoDel<HOGE> HOGE_ARY; // 配列クラスの定義
HOGE_ARY HogeAry; // 配列のインスタンス
             // 配列に要素を追加
HogeAry.Add( new HOGE); // このobjは配列破棄時に自動的にdeleteされる

てな感じ。簡単ですよねぇ。えと、ソース検証してないのでよろしく。
ちなみに適切に使ってる分にはHOGEの子孫群のコンポジットな配列でも、
ちゃんとdeleteしてくれます(デストラクタがvirtualは必須)。


返信引用
Baby Chicken
 Baby Chicken
(@Baby Chicken)
ゲスト
結合: 16年前
投稿: 45
Topic starter  

仲澤@失業者様

ご指導ありがとうございます。とっても難しく感じるのですが、理解できるように頑張りま
す。


返信引用
とおりすがり
 とおりすがり
(@とおりすがり)
ゲスト
結合: 23年前
投稿: 180
 

全然違う話ですみませんが、STLにポインタを入れるのがよろしくないのは
なぜでしょう?自分はとてもよく使っています。
理由としてはOperator=の実装が要らないからだったり特定画面のWndハンドルだったり
するからなのですが・・・


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 21年前
投稿: 600
 

僕もそんなに忌み嫌うほどのこっちゃない思います。
問題は追加/削除および共有が起こったときにややこしくなるってとこですから。


返信引用
とおりすがり
 とおりすがり
(@とおりすがり)
ゲスト
結合: 23年前
投稿: 180
 

共有とかはクラスにコンテナ押し込めてconst返したり
シングルトンとか使いますねぇ…
ネットワークでどうなるかはやったことないからわかりませんが


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

共有が起こった時にそれをちゃんと認識した上で管理していないと
削除した時に問題が怒ると言う部分が一番面倒でしょうねぇ。
STLから直接参照している分には良いのでしょうけれど、
STL内に格納されているポインタが別の場所に一人歩きしてしまうと
STLから削除する時にうかつに削除できなくなります。
その部分が一番問題なんじゃないかと思います。

きっちりかっちり管理されていれば問題なさそうですけどね。
もしくはsharedptrで被せてSTLに突っ込むのが一番無難そう。


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

うわー。

誤)
削除した時に問題が怒ると言う部分が一番面倒でしょうねぇ。

正)
削除した時に問題が起こると言う部分が一番面倒でしょうねぇ。

まあ、使っているところを勝手に削除されたら怒るでしょうけれど。(^^;


返信引用
maru
 maru
(@maru)
ゲスト
結合: 17年前
投稿: 358
 

> STLにポインタを入れるのがよろしくないのは
> なぜでしょう?
ポインタはバグの宝庫。なので、
STLはコンテナにオブジェクトそのものを格納出来るのに、わざわざバグが発生しやすい
ポインタを使うことはないんじゃないの?くらいでは?

> sharedptrで被せてSTLに突っ込むのが一番無難そう。
御意。


返信引用
固定ページ 1 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました