0

次のようなポインターのベクトルがあります。

vector<Item*> items;

クリアしたい。私はもう試した:

for (unsigned int i = 0; i < items.size(); i++)
    delete items.at(i);
items.clear();

while (!items.empty())
{
    delete items.back();
    items.pop_back();
}

while (!items.empty())
{
    delete items.at(0);
    items.erase(items.begin());
}

、 と

while (!items.empty())
    delete items.at(0);

すでに削除されたオブジェクトの削除や範囲外のベクトル反復子など、これらのすべてが何らかの理由で爆発します。

私は何をしますか?同じベクターを再利用して、後で Item ポインターを追加できるようにしたいと考えています。クリアせずに使用するだけdeleteでは、ジャンク ポインターがそこに残りますよね?

編集:わかりました、shared_ptrs に切り替えました。今私が持っています

vector<shared_ptr<Item> > items;

それでも、実行するとitems.clear();、「ベクトル反復子に互換性がありません」というエラーが表示されます。私はまだ何を間違っていますか?

4

6 に答える 6

2

私はあなたのすべての削除方法でテストを実行しましたが、そのうちの 1 つが機能しませんでした。それらに関するコメントについては、以下のコードを参照してください。

「どうすればよいか」というあなたの質問に答えるために、削除時にセグフォルトしたときに私がすること
は次のとおりです。
2)メモリをまだ削除していないことを確認してください(削除した場合、たとえそれが私のものであったとしても、それは今ではありません)。

3) seg-fault がコードの 1 つのセクションによって引き起こされていると確信している場合は、それを別のプロジェクトの小さなテスト ケースに分割します (質問で行ったように)。それからそれで遊んでください。小さなプロジェクトでコード例を一番上で実行した場合、最後のプロジェクトでセグメンテーション違反が発生し、他のすべてのケースで削除が機能していることに気付くでしょう。このようにコードを分解すると、ベクトルにこれらをどのように格納しているかを追跡して、それらの所有権をどこで失っているかを確認する必要があることがわかります (削除、またはそれらを削除するものに渡すなど... )。

補足: 他の人が言っているように、スマート ポインターを使用できる場合は、スマート ポインターがメモリ管理を行ってくれます。ただし、ここで学習を続けて、愚かなポインターの使用方法を理解してください。ブーストをインポートできない場合や、メモリ管理を QT に任せることができない場合があります。また、コンテナーにポインターを格納する必要がある場合もあるため、それを行うことを恐れないでください (IE: QT 開発者は、参照などの代わりにポインターを使用してウィジェットを格納することを強くお勧めします)。

#include <vector>

using namespace std;
class Item
{
public:
    int a;
};

int main()
{
    vector<Item *> data;

    for(int x = 0; x < 100; x++)
    {
        data.push_back(new Item());
    }

    //worked for me, and makes sense
    for(int x = 0; x < 100; x++)
    {
        delete data.at(x);
    }
    data.clear();

    for(int x = 0; x < 100; x++)
    {
        data.push_back(new Item());
    }
    //worked for me, and makes sense
    while (!data.empty())
    {
        delete data.back();
        data.pop_back();
    }
    data.clear();

    for(int x = 0; x < 100; x++)
    {
        data.push_back(new Item());
    }

    //  //worked for me, and makes sense
    while (!data.empty())
    {
        delete data.at(0);
        data.erase(data.begin());
    }

    for(int x = 0; x < 100; x++)
    {
        data.push_back(new Item());
    }

//  //This one fails, you are always trying to delete the 0th position in
//  //data while never removing an element (you are trying to delete deleted memory)
//  while (!data.empty())
//  {
//      delete data.at(0);
//  }


    return 0;
}
于 2012-04-19T23:13:06.070 に答える
0

さて、私はやった。長い時間、たくさんのアスピリン、そしてたくさんの抜け毛の後、私はついに問題が何であるかを理解しました. このポインターのベクトルを含むクラスを含む特定のデストラクタを以前に呼び出していたことがわかりました。デストラクタを呼び出すだけで、すべての静的データ メンバーが消去されるとは思いもしませんでした。私は時々C++が嫌いです。

于 2012-04-24T20:27:00.083 に答える
0

次のようなスマート ポインターのベクトルを使用します。

vector<shared_ptr<Item> > myVect;

または、Boost でPointer Containersライブラリを使用します。

これを行って再利用する方法があるかもしれませんが、特にブーストのポインターコンテナーがヘッダーのみのライブラリであることを考えると、エラーが発生しやすく、より多くの作業が必要になるようです。

于 2012-04-19T22:49:47.030 に答える
0

boost::shared_ptr<Item>ベクトルがクリアされるか、要素が削除されると、それらは削除されます。

于 2012-04-19T22:50:01.370 に答える
0

私は何をしますか?

ポインターのベクトルを維持しないでください。本当に、それはほとんどの場合間違いであり、メモリ管理を処理するベクトル (RAII) の設計と戦っています。deleteすべてのポインター を呼び出す必要があります。

ポインターのベクトルが本当に必要ですか? もしあなたが本当にそうしているなら (そう思っているだけではなく、何らかの理由で実際に必要なのです)、スマート ポインターを使用してください。

ベクターは動的にメモリを割り当てます。意図したとおりに使用してください。

于 2012-04-19T22:50:18.983 に答える
0

ベクトルで同じポインターが繰り返されているように聞こえます。それらを一度だけ削除していることを確認するには、それらをに転送しstd::setてそこで削除します。例えば、

std::set<Item*> s( items.begin(), items.end() );
items.clear();

while ( !s.empty() )
{
    delete *s.begin();
    s.erase( s.begin() );
}
于 2012-04-19T23:15:17.767 に答える