• ベストアンサー

C++ Vectorのデストラクタ

C++ Vectorのデストラクタ boost::any型のVectorに自作クラスをpush_backで入れると、なぜかその自作クラスのデストラクタが呼ばれてしまって困っています。 またそのクラスの関数を実行すると同じようにデストラクタが呼ばれてしまいます。 

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

  • ベストアンサー
  • hidebun
  • ベストアンサー率50% (92/181)
回答No.1

boost:anyのVectorについてではないですが、 STLのvectorでは、オブジェクトの再配置が起こります。 同様の理由じゃないでしょうか? http://homepage2.nifty.com/well/STL.html vector のメモリの再配置にかかわる問題です。vector は、可変長配列であるがゆえに、配列を伸ばす操作を行うと、あらかじめ用意してあったメモリ領域をはみ出してしまう場合があります。そのようなときには、十分な長さの新しいメモリ領域をとって、現在の内容をそこにコピーし、元のメモリ領域を開放するという動作を行います。この場合、元のメモリ領域を指していたポインタや参照は、使えなくなります。

whiterozes
質問者

お礼

自己解決しました。boost::anyのダウンキャストが理由でした。おっしゃって頂いたvectorの再配置にも引っかかっていました。ありがとうございました。

その他の回答 (1)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

「boost::any型のVector」というのがよくわからんのだけど.... C++ には「Vector」というものはなかったような気がするし. 可能なら, どんなコードを書いたのか見せてもらえませんか?

whiterozes
質問者

お礼

自己解決しました。boost::anyのダウンキャストが理由でした。 BoostはC++を作った委員会の人が作ったライブラリ(?)です。any型は全ての型やクラスを保存できるすごく便利なクラスです。 visual studioであればプロトタイプ版が入っています。ちなみにvectorはSTLの奴です。

関連するQ&A

  • C++のクラスの仮想デストラクタについて

    C++のクラスの仮想デストラクタについて教えてください。 デストラクタは、クラスの名前の前にチルダを付けたものが名前になりますが、とあるクラスの継承クラスは、その親クラスとクラス名が違うので、デストラクタの名前も親クラスのものとは別になる。つまり。継承関係のあるクラスでもデストラクタはオーバーライドせず、各クラス毎に別の名前で存在する、ということになると思います。 ですので http://wisdom.sakura.ne.jp/programming/cpp/cpp31.html このページの下部にあるように、「デストラクタは、派生クラスから基本クラスへ向かって順番に呼び出される」というのもなんとなく合点が行きます。 しかし、仮想デストラクタというものがあることを知りました。 上記のようにデストラクタは継承関係のあるクラス間でも、それぞれクラス毎に作ればよいと思っていましたが、子クラスの方でオーバーライドする必要がある場合があるのでしょうか。あるとすれば、それはどんな場合なのでしょうか。 また、上記のURLでは、「C++ 言語のデストラクタはオーバーライドを行いません」と書いてあり、なんだかよく分からなくなってきました。仮想デストラクタというものが存在するのに? どなたか詳しい方いらっしゃいましたらご教示頂けると幸いです。

  • 継承元のpublicなメンバ関数を隠ぺいしたい

    C++です.(VC++2013) 親クラスではpublicで宣言されているメンバ関数があり,継承後はこのメンバ関数を隠ぺいしたいときはどのようにすればよいのでしょうか. 具体的には,std::vectorから派生したクラスを定義し,この独自クラスのインスタンスへ要素を追加する場合は,新しく独自に定義した関数を通じて行います. そのため,push_back()を呼べないようにしたいのです. 自分で作成した関数には,pushという名前をつけたいので,単純に自分の要素追加の関数をpush_backという名前でオーバーライドすることはできません. push関数内では,push_backした後,即座にsortしたいので,push_backをいう名前をつけたくないのです. とりあえずは,派生クラスでprivateにpush_backをオーバーライドし,自分で作った要素追加の関数で使うpush_backはstd::vectorのものを用いることを明示することでできました. 他にも何かやり方があれば,ご教授下さい.

  • STLベクトルコンテナ

    vectorの1次元目の要素と1次元目のサイズを常に持ち回す方法しか思いつきません。 int dim1size = 2; int dim1ite = 0; vector<vector<char *> > vec; vec.resize(dim1size); vec.at(dim1ite).reserve(2); どこかの関数で vec.at(dim1ite).push_back("浅倉"); vec.at(dim1ite).push_back("東京"); dim1ite++; どこかの関数で vec.at(dim1ite).push_back("稲垣"); vec.at(dim1ite).push_back("大阪"); dim1ite++; どこかの関数で vec.at(dim1ite).push_back("内山"); vec.at(dim1ite).push_back("名古屋"); dim1ite++; このようなソースです。 dim1sizeとdim1iteを持ち回さなくてもvecだけで1次元目のサイズを気にすることなくpush_backを実行するよい方法はありませんか? 上記ソースではpush_back("内山");の前にresizeが必要です。これを自動でやってほしいのです。

  • 自作関数におけるコンストラクタとデストラクタ

    お世話になります。 定義クラスにおいて、オブジェクト生成時と解放時にコールされる関数(__construct()、__destruct())は有名ですが、クラス内に定義した自作関数がコールされた時と終了(?)した時に、コールされる関数は存在するのでしょうか。 現在、自作した関数の最初と最後に、ログ書き込み用の自作関数を仕込む事で、希望した挙動を実装していますが、自作関数におけるコンストラクタ、デストラクタの様な関数があれば楽かなと、色々検索したのですが、今ひとつヒットしませんでした。 ご存じの方、情報提供頂ければ嬉しいです。

    • 締切済み
    • PHP
  • デストラクタについて

     C++初心者です。 delete [] tt ; でデストラクタが要素数だけ実行されるのは 確認しています。 ところがその実行後に、例えば、 cout << tt[3].test() << endl ; としますと、ちゃんと表示されます。 消滅したはずのオブジェクトが使えるのはど うしてでしょうか? どなたかお教え願えませんでしょうか。 どうぞよろしくお願いします。

  • c++のvector::erase

    vector::eraseについて質問させてください。 vector::eraseでググるとforループ内でのeraseの仕方は 書いていあるのですが、単純に1要素だけeraseする 例が見当たらなかったので教えてください。 1要素を削除する場合、 以下のような書き方でよろしいのでしょうか? いちおう正しく動作しているようです。 ただ、疑問なのは途中の要素[2]を削除しているので、 後半の要素が詰め直されているのか、 そのあたりが自信がなくて不安です。 vector<string> v; v.push_back("0a"); v.push_back("1a"); v.push_back("2a"); v.push_back("3a"); v.push_back("4a"); v.erase( v.begin() + 2 );//v[2]を削除 //結果表示 for(unsigned int i=0; i<v.size(); i++){ cout<<v[i]<<"\n"; } cout<<endl;

  • vectorを引数として使いたいのですがエラーが出てしまいます

    vectorを引数として使いたいのですがエラーが出てしまいます 以下のようなコードでコンパイルでエラーが出てしまうのですがどうしたら良いでしょうか。 class car{ public: int tire; int engine; } というクラスを作ります。 main関数内で function(car a[]);//関数の宣言 int main(){ std::vector<car> car1(0);//car型のcar1を作成 std::vector<car>::reference car1rf=car1.front(); function(car1rf);//関数に代入 } function(car a[]){ car test; test.tire=1; a.push_back(test); } としてpush_backを外部関数で行いたいのですが、エラーが出てしまいます。 どうしたら良いでしょうか。

  • vector間における効率的な値の比較

    2つのベクターに入ったdoubleの網羅的な比較を行う関数をC++で書こうとしています。 (VC++ 2008) doubleのベクター vctr_1 , vctr_2 があるとします。 vctr_1 には (100.0, 200.5 , 300.1 , 400.0 ) vctr_2 には(50.0 , 70.2, 100.1, 220.0 , 300.0 ) というdouble の値が入っていて vctr_1の値のうち、vctr_2に近い値(誤差0.2以内)が見つかるものを.新しいベクターとして返すという処理を考えています。 この場合 100 : 100.1 と300.1: 300.0 が 誤差 0.2 未満で近い値といえ、100 と300.1が格納されたベクターを返す、という処理です。 私の考えた方法はベクターaの各要素に対してベクターbの各要素をループで比較する、というものでした。 以下コード ---------------------------- //比較を行う関数。ベクター1、2 要素の比較をし誤差内の数値をベクター1からとりだし、別のベクターとして返す。 vector<double> compare_doubles_with_tol(vector<double> v1,vector<double> v2 , double tol ){ //似た値を格納するベクター vector<double> v_match; //ベクター1に関してループ vector<double>::iterator it1 = v1.begin(); while( it1 != v1.end() ){ //ベクター2に関してループ vector<double>::iterator it2 = v2.begin(); while( it2 != v2.end() ){ //誤差内の値を見つける if( fabs(*it1 - *it2) < tol ){ v_match.push_back(*it1); } ++it2; } ++it1; } return v_match; } int main() { //ベクター1 std::vector<double> vctr_1; vctr_1.push_back(100.0); vctr_1.push_back(200.5); vctr_1.push_back(300.1); vctr_1.push_back(400.0); //ベクター2 std::vector<double> vctr_2; vctr_2.push_back(50.0); vctr_2.push_back(70.2); vctr_2.push_back(100.1); vctr_2.push_back(220.0); vctr_2.push_back(300.0); //誤差0.2内で似た値があるものを新たなベクターとして得る。 vector<double> matched = compare_doubles_with_tol(vctr_1,vctr_2,0.2); for (int i = 0 ; i < matched.size() ; ++i){ cout << matched[i]<<endl; } return 0; } ------------------------- このコードで望んだ結果は得られますがループの繰り返しを行っていて処理が遅くなってしまいます。実際の仕事ではベクターの要素数が100前後のものを非常に数多く処理しなければならず、このままでは処理時間が膨大なものになってしまいそうです。 このような場合どのような処理、コードを作成すれば処理速度の向上が望めるでしょうか。

  • コンストラクタ・デストラクタ

    プログラミング言語はC++ C++を触り始めたばかりの素人です。 コンストラクタとデストラクタについて質問です。 下記に参考にしているウェブページから簡潔にしてコードを書いてみました。 コンストラクタ、デストラクタの中はそれぞれに、○○が呼び出されましたと書いてあるだけでよく分からなかったので別のウェブページを見たら コンストラクタは Sample::Sample(){ n=0; } みたいな例があったのですが、このように変数に予め何かの値を代入しておくという事で合ってますか? デストラクタは理解できていません。 下記の例では、どのような処理を書けばいいのでしょうか? #include<iostream> using namespace std; class Sample { private: int n; public: void Show(); Sample(); ~Sample(); }; void Sample::Show() { cout << n << endl; } Sample::Sample() { // n=0; std::cout << "コンストラクタが呼び出されました" << std::endl; } Sample::~Sample() { // どんな処理? std::cout << "デストラクタが呼び出されました" << endl; } main() { Sample sample; sample.Show(); return 0; } 実行結果 コンストラクタが呼び出されました 1     ←コンストラクタ関数内の//を削除で0になることは確認 デストラクタが呼び出されました

  • [PHP] デストラクタについて教えて下さい

    あるPHPの入門書にデストラクタについての解説があります。 *デストラクタ 「コンストラクタとは反対に、オブジェクトが破棄されるタイミングで実行されるのがデストラクタです。名前は __destructに固定されている。 デストラクタには、クラスの中で使用したリソースを破棄するなど、主に終了するときの処理を記述するのが一般的です。」 とあります。 以下のような記述をしました。(person.php) <?php class Person{ public $lastName; public $firstName;  public function __construct($lastName, $firstName){ $this->firstName = $firstName; $this->lastName = $lastName; } public function show(){ print "<p>私の名前は {$this->lastName} {$this->firstName}です。</p>"; } public function __destruct(){ print "<p>インスタンスが破棄されました。<p>";  } } ?> 上の記述をインスタンス化する記述です。(instancne.php) <?php require_once('person.php'); $p = new Person('田中', '幸太郎'); $p->show(); ?> <表示結果> 私の名前は 田中 幸太郎です。 インスタンスが破棄されました。 となります。試しにもうひとつインスタンスを追加します。 <?php require_once('person.php'); $p = new Person('田中', '幸太郎'); $p->show(); $p1 = new Person('鈴木', '京子'); $p1->show(); ?> <表示結果> 私の名前は 田中 幸太郎です。 私の名前は 鈴木 京子です。 インスタンスが破棄されました。 インスタンスが破棄されました。 説明にある、 「オブジェクトが破棄されるタイミングで実行されるのがデストラクタです。」 「デストラクタには、クラスの中で使用したリソースを破棄するなど、主に終了するときの処理を記述するのが一般的です。」 これらの意味がわかりません。 コンストラクタの 「new 演算子によってインスタンス化されるタイミングで実行される」 「プロパティの初期化」 などの意味は理解できているつもりです。 デストラクタを使うと「オブジェクトが破棄される」、「クラスの中で使用したリソースを破棄する」と ありますが、『一度インスタンスを作るとクラス内のリソースが破棄されるのかな?』と思い ためしにもう一つインスタンスを作成しました。上記の通り問題なく使えています。 膨大な記述になると、クラス、この場合は 「class Person」」は再利用出来なくすると言った意味になるのでしょうか? 他の教材やネットで検索してみたりしたのですが、イメージがつかめません。 以下のPHP公式のサイトから考えてみると、クラス内で参照できるものがなければ、コールされるという風に解釈できるかもしれませんが、意味がわかりません。 デストラクタ(__destruct)はコンストラクタ(__construct)の反対というように記述されているものもありますが余計に意味が分かりません。 初学者にもわかるようにデストラクタについて教えてもらえないでしょうか? またどういうケースで利用するのかもよく分かりません。 そのあたりも併せて教えて下さい。 宜しくお願いいたいます。 (参考) デストラクタ __destruct(): void PHP には、C++ のような他のオブジェクト指向言語に似たデストラクタの概念があります。 デストラクタメソッドは、 特定のオブジェクトを参照するリファレンスがひとつもなくなったときにコールされます。 あるいは、スクリプトの終了時にも順不同でコールされます。 https://www.php.net/manual/ja/language.oop5.decon.php

    • ベストアンサー
    • PHP

専門家に質問してみよう