• ベストアンサー

VectorなどSTL?テンプレートの使い方

戻り値がポインタの場合、関数から抜け出すと値の保証が無いので、それを使用する場合は、変数にコピーして使うと値は残る(アクセス可能)と理解しています。 char tmp[128]; strcpy(tmp, test()); それで、次のような vector??を使った場合、表示の場合は問題ないかもしれませんが、その後、値を使い続ける場合、ポインタのままでよいのか疑問に思っています。 以下のソースは勝手気ままに記述したものですが、 VC++6でエラーなく動作(とりあえず動く)しているのですが、今後発生する問題など知りたいです。 #include "stdafx.h" #include <string> #include <iostream> #include <vector> #include <sstream> using namespace std; class A { string str; vector<A *> v_cls; public: A(){ } // デフォルトコンストラクタが必要? A(string s){ str = s; } void PrintData(void){ // 表示 cout << str << endl; } // 1から9までの[0]-[9]の文字列を作成 vector<A *> ArraySet(void){ stringstream ss; for (int i=0; i < 10; i++){ ss.str(""); ss << "function [" << i << "]\n"; v_cls.push_back( new A( ss.str() ) ); } return v_cls; } }; void main(void){ // 1から9までの[0]-[9]の文字列を作成 // これは問題ないと思う vector<A *> v; stringstream ss; for (int i=0; i < 10; i++){ ss.str(""); ss << "[" << i << "]\n"; v.push_back( new A( ss.str() ) ); } v[1]->PrintData(); v[3]->PrintData(); ////cout << v.size(); // クラス自身にvector配列?を返す処理 // とりあえず動いているだけ??? A x; vector<A *> ret = x.ArraySet(); // このような代入でも問題ないのでしょうか? ret[5]->PrintData(); // 表示だけなので、問題なし? ret[0]->PrintData(); // vやret, xの解放仕方とタイミングはどうすればよいのでしょうか? }

質問者が選んだベストアンサー

  • ベストアンサー
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.3

> deleteの場所が良くわかっていません。 vector<A*>オブジェクトのデストラクタが呼ばれる直前で、各要素に対してdeleteを行ってください。ただし、デストラクタが呼ばれるところであればどこでもdeleteすればよいというものではなく、本当に要素を解体したいところでのみ行う必要があります。 ポインタを要素に持つコンテナは、このように所有権が不明瞭になります。特定の関数の中だけで使う局所的なオブジェクトや、クラスのメンバ関数からしか操作しないデータメンバの場合はまだよいのですが、関数の引数や返却値に使うのは、あまりよい設計とはいえません。 > 例外処理は自身ないのですが、ソースが長いと聞きたい焦点がぼけると思いまったく書きませんでした。 今後発生する問題を知りたいとのことですので、例外処理は省略すべきではありません。

tobasu
質問者

お礼

ポインタを要素に持つコンテナを改め、以下のように変更しました。 これで問題ないと思いますが、突っ込み所があれば、ご指摘お願いします。 ※コンテナ?とイテレータ?でポインタを使わない場合は、勝手に解放してくれるのでしょうか? #include "stdafx.h" #include <string> #include <iostream> #include <vector> #include <sstream> using namespace std; class A { string str; vector<A> v_cls; public: A(){} A(string s){ str = s; } ~A(){} // 表示 void PrintData(void){ cout << str << endl; } // 1から9までの[0]-[9]の文字列を作成 vector<A> ArraySet(void){ stringstream ss; for (int i=0; i < 10; i++){ ss.str(""); ss << "[" << i << "]"; v_cls.push_back( A( ss.str() ) ); } return v_cls; } }; void main(void){ // 1から9までの[0]-[9]の文字列を作成 // これは問題ないと思う A x; vector<A> ret = x.ArraySet(); // この代入は問題ないのでしょうか? // この位置からの例外処理は正しいですか? try{ ret[5].PrintData(); cout << "OK 5" << endl; ret[0].PrintData(); cout << "OK 0" << endl; ret[10].PrintData(); cout << "OK 10" << endl; } catch (...) { // 一般的な例外処理の書き方がわかりません。 cerr << "例外が発生しました。" << endl; } // xはmainからぬけると、消滅解放してくれると思いますが、 // ArraySetメソッドでpush_backした分は解放しなくてもよいのでしょうか? }

その他の回答 (2)

  • asuncion
  • ベストアンサー率33% (2127/6289)
回答No.2

> strcpy(tmp, test()); これがうまくいくかどうかは、test() の実装によります。 こう書けば必ずうまくいく、というものではありません。

tobasu
質問者

補足

char *test(void){ char dmy[] = "轟々と、隼は行く";  return dmy; } これでもダメですか?

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.1

突っ込みどころ満載ですが、とりあえず致命的な部分だけ指摘します。 vにせよretにせよ、コンテナの要素がポインタですので、解体時には、各要素に対してdeleteを行う必要があります。(現状ではリークします) そもそも、コンテナの要素にポインタを使うのは、所有権が不明瞭になることもあり、あまりよい設計とはいえません。 もう一点、例外に対する配慮が全くなされていません。現状では、どこかで例外が発生すると、即クラッシュします。

tobasu
質問者

お礼

戻り値=関数・オブジェクトメソッドが私的に スマートだと勝手に思っているのですが、この書き方でよい設計にする場 どのようにするのでしょうか? deleteの場所が良くわかっていません。 例外処理は自身ないのですが、ソースが長いと聞きたい焦点がぼけると思いまったく書きませんでした。

関連するQ&A