おれ、遅く!
あなたの記憶でかなり狂ったことをしているので、最初から始めましょう。
あなたは3つの要素を持つ単一のベクトルを持っています。ポインタを使ってそのベクトルを参照したいとします。どのように見えるかを見てみましょう:
vector<double> mv;
mv.push_back(233);
mv.push_back(234);
mv.push_back(654);
// No no no no! You don't have to `new` a pointer that
// you're going to assign to something else!
// This is called a memory leak, and it means you've just wasted (!!!)
// C++ memory! Don't do it
// vector<double>* new_mv_pt = new vector<double> (3);
// Instead, do this:
vector<double>* ptr_to_mv = &mv; // No leak, immediately points to a vector<double> mv;
最初のビットが処理されます。さて、少し深めてみましょう。ベクトルへの参照のベクトルを保存します。申し訳ありません。それについてはいくつかの方法があります。さんがmv
や他のものの例に戻りましょう:
vector<double> mv;
mv.push_back(233);
mv.push_back(234);
mv.push_back(654);
vector<double>* ptr_to_mv = &mv;
// So far so good. Now, based on your question, you want
// to have a list of these to point to. So:
vector<vector<double>*> vop;
vop.push_back(ptr_to_mv); // All clean.
あなたのコード内のこの時点で、あなたは*
または使用して、それを間接参照し、その後、vector<double>*
に到達するために.at()
またはoperator[]
でvop
にアクセスする必要が->
が直接その上で動作するように:このすべてがmv
をご参照しているので
std::vector<double>* ptr_to_vector = vop[0]; // Got my pointer
std::cout << ptr_to_vector->at(0) << std::endl; // Prints '233'
をこれが233を印刷します。別の答えのコメントでは、これらのポインタを削除するとアサーションが得られると言っています。 これは、あなたが物事を2回削除しているので、起こるはずです!
あなたは長い間前に宣言したmv
を覚えていますか?まあ、あなたはそれを動的なベクトルにしていませんでした。あなたはnew
ではありませんでした。それはポインタではありません。したがって、関数が終了すると自動的に削除され、デストラクタが呼び出され、スタック上にが死ぬ。。 ptr_to_vector
またはptr_to_mv
を見ると、それらはすべてmv
を参照しており、それ自体が消去されます。
あなたが削除を呼び出すと、あなたはmv
の削除を呼び出そうとしています(あなたが指していることです)、あなたは二重削除しています!
mv
へのポインタがある場合、それを削除しないでください。これはスタックベースの変数です。それは自分自身をきれいにするでしょう。
まだまだ続きますか?偉大な、のは、もう少しそこに取得してみましょう:あなたは、ベクトルをアップnew
する必要が理由があるのなら、私は前にあなたに言ったとして今
、あなたは、(旧ポインタでそれを上書き割り当てませんあなたは記憶を残すでしょう)。それだけだから、我々は、両方のないよう、別の1が、削除を呼び出すことによってクリーンアップする必要がvop
、内側と2つのポインタを持っている:
// Our vector of double vector pointers
vector<vector<double>*> vop;
vector<double> mv;
mv.push_back(233);
mv.push_back(234);
mv.push_back(654);
// References a stack variable: don't delete
vector<double>* ptr_to_mv = &mv;
vop.push_back(ptr_to_mv);
// Makes a fresh copy of mv. You must delete this
// manually
vector<double>* fresh_ptr = new vector<double>(mv);
(*fresh_ptr)[0] = 1337;
// changes only data in fresh_ptr, not `mv`
vop.push_back(fresh_ptr);
/* Blah blah blah, work */
// Functions about to exit, gotta clean up!
delete fresh_ptr;
//delete ptr_to_mv; // NO.
//delete vop[0]; // NO!
//delete vop[1]; // ... Already deleted from fresh_ptr
// ... This is going to get tedious if we don't have a fresh_ptr
// for every vector we need!
上記
問題を示しています。あなたは完全に新鮮な新しいポインタを作ります自動的にクリーニングするmv
への参照!ベクトルをループしてすべてを削除すると、その厄介なアサーションが発生します。私たちはそれをどのように扱い、まだ必要なクリーンアップを得るのでしょうか?
ダーティークイックソリューション1はちょうどdelete vop[1]
/fresh_ptr
になります。より良い解決策は、new
のリソースを使うときはいつでも、std::unique_ptr
と呼ばれるこの素敵なものにまとめます。コードは次のようになります:
そしてそこにコメントアウトされたコードをすべて削除してください。突然、あなたのものは笛のようにきれいです!もちろん
、今、あなたのために私が持っている最後の質問です: あなたはそれをどのような地獄をやっているのは、ベクトルのポインタの参照にポインタへのすべてのこれらのポインタを必要としますか?
まず、回答を得てください。第二に、これは恐ろしい考えであることに気付く。なぜなら、最初に使用するポイントの半分以上の、あなたのためにメモリを管理するベクターの能力を排除しているからです。 –
私は、なぜ彼が最初にベクターへのポインタを持っているのか理解しようとしています。これは、特に同じ関数/クラスにある場合、このようにするのは概念的に意味がありません。 –