0

vector最近、特定のオブジェクトのポインターの要素にアクセスしようとすると、セグメンテーション違反が継続的に発生する理由について混乱しました。問題を解決することはできませんでしたが、オブジェクト ポインターを にプッシュした後、コピーが保存されていると考えてそれvectorを呼び出したためだと思われます。deletevector

次のコードでは:

std::vector<SomeObject *> testvector;
SomeObject * testobject = new SomeObject(/* some arguments here, call constructor */)
testvector.push_back(testobject);
delete testobject; // does this affect the element in the vector?

デバッガーは、ベクターに追加されるポインターが実際に適切なデータを持っていることを確認しますが、それらに対して delete を呼び出すと、ベクター内の要素が影響を受けるかどうかはわかりません。ベクターは単なるコピーを保存しますか? オブジェクトで削除を呼び出すと、ベクトル内のポインターで削除が呼び出されているのではないかと思いますが、よくわかりません。

delete を呼び出した後、ベクトル内のデータを出力しようとしましたが、次のようになりました: ??? ?? ???? ???

そして、削除の呼び出しがベクター要素に影響を与えたと想定しています。これは事実ですか?ベクターにポインターを追加した後、ベクター内の要素に影響を与えずにオブジェクトを安全に解放できると思っていましたが、割り当てられなくなったメモリにアクセスしてしまうようです。delete の呼び出しはベクトル内のポインターに影響しますか?

4

4 に答える 4

4

「delete の呼び出しはベクトル内のポインターに影響しますか?」

ポインターには影響しません。このポインターが指すオブジェクトが存在しなくなったため、このポインターを使用して呼び出された動作に影響します。を呼び出すdeleteと、オブジェクトが削除され、無効な (古い、ぶら下がっている) ポインターを使用してそのオブジェクトを操作しようとすると、動作は undefinedになります。

std::vector<SomeObject *> testvector;
SomeObject * testobject = new SomeObject()
testvector.push_back(testobject);

ポインターのベクターを構築し、インスタンスを作成してSomeObject、このオブジェクトのアドレスをベクターにプッシュします。次に、電話すると:

delete testobject;

std::vectorオブジェクトが削除されたことを知る方法はありません。ベクターには、オブジェクトが削除されるまでに無効になった古いポインターがまだ含まれています。可能な解決策は、 のようなスマート ポインターのベクトルを使用することです、最初にポインターのベクトルを使用するかどうかを検討する必要があります。たぶん、より合理的な方法になるでしょう。shared_ptrstd::vector<SomeObject>

于 2013-11-05T23:33:09.453 に答える
1

ベクトルには、オブジェクト自体ではなくポインターが含まれます。したがって、オブジェクトを削除すると、対応するポインタは無効になります。

于 2013-11-05T23:35:01.490 に答える
1

はい、testobjectベクトルに挿入された要素と両方が同じアドレスを指しています。それらの 1 つを削除すると、別のポインターがダングリング ポインターになり、逆参照は未定義の動作になります。

std::unique_ptrやなどのスマート ポインターを使用できますstd::shared_ptr

std::vector<std::shared_ptr<SomeObject>> testvector;
std::shared_ptr<SomeObject> testobject(new SomeObject);
testvector.push_back(testobject);

また

std::vector<std::unique_ptr<SomeObject>> testvector;
std::unique_ptr<int> testobject(new SomeObject);
testvector.push_back(std::move(testobject));
// After `std::move` you can not use `testobject` anymore!
于 2013-11-05T23:35:52.960 に答える
1

ポインターをコピーする場合、オブジェクト自体ではなく、オブジェクトのアドレスのみをコピーします。つまり、ベクトル内のポインターとベクトル外のポインターは、削除を呼び出したときにまだ同じものを参照していました。

デバッガーが一見有効なデータを表示している可能性があるのは、何かを削除してもメモリが必ずしも上書きされるとは限らないためです。必要に応じて後で別のもので使用できるように、単に「無料」とマークされています。

于 2013-11-05T23:36:40.790 に答える