0

重複の可能性:
C ++ベクトルの割り当てを正しく解除または削除するにはどうすればよいですか?

ベクターに割り当てたメモリを削除しようとして問題が発生しました。list.clear()を呼び出しても、メモリの割り当てが解除されません。

だから私はSetと呼ばれるテンプレートベースのクラスにこのようなコードを持っています

template <class T>
class Set {
public:
    // stuff
private:
    int size;
    std::vector<T> list;
};

そしてコンストラクターでは、ベクターにメモリーを割り当てました。だから私はlist=new std::vector;と呼びます。

あなたの興味のために、これが私のコピーコンストラクターと代入演算子です。これは私がベクトルにメモリを割り当てる場所でも見たものです。

template <class T>
Set<T>::Set(const Set& aSet)
{
    size = aSet.size;
    list->clear();
    list = new vector<T>;
    for (int i = 0; i < size; ++i) {
        list[i] = aSet.list[i];
    }
}

template <class T>
Set<T>& Set<T>::operator=(const Set& right)
{
    if (this != &right) {
        list->clear();
        size = right.size;
        list = new vector<T>;
        for (int i = 0; i < size; ++i) {
            list[i] = right.list[i];
        }
    }
    return (*this);
}

デストラクタには、すべての要素を削除してからメモリの割り当てを解除するlist.clear()があります。

しかし、問題は、.outファイルでvalgrindを実行すると、メモリが確実に失われたことを示しており、なぜこれを示しているのかわかりません。Stackoverflowでいくつかの質問を読みましたが、基本的にすべてを試しました。clear()を試し、ベクターを削除しましたが、うまくいきませんでした。次に、erase(list.begin()、list.end())を試みましたが、それも機能しませんでした。

私の思考プロセスは、Set * aSet =newSet;を使用しているというものです。私のメインクラスでは、intはオブジェクトではないため、list.clear()を呼び出しても解放されません。これは正しいですか?メモリを正しく削除するにはどうすればよいですか?

助けてくれてありがとう。

Edit1=リスト*をsetListに変更

私の新しいコンストラクターと代入演算子:

template <class T>
Set<T>::Set(const Set& aSet)
{
    size = aSet.size;
    setList.clear();
    setList = aSet.setList;
}

template <class T>
Set<T>& Set<T>::operator=(const Set& right)
{
    if (this != &right) {
        setList.clear();
        size = right.size;
        setList = right.setList;
    }
    return (*this);
}

Valgrindは、私が同じ量の失われたメモリを持っているとまだ報告しています。私のデストラクタにはまだlist.clear()があります

Valgrindログ:

==11398== 
==11398== HEAP SUMMARY:
==11398==     in use at exit: 62,969 bytes in 352 blocks
==11398==   total heap usage: 540 allocs, 188 frees, 68,046 bytes allocated
==11398== 
==11398== LEAK SUMMARY:
==11398==    definitely lost: 8,624 bytes in 14 blocks
==11398==    indirectly lost: 1,168 bytes in 5 blocks
==11398==      possibly lost: 4,829 bytes in 56 blocks
==11398==    still reachable: 48,348 bytes in 277 blocks
==11398==         suppressed: 0 bytes in 0 blocks
==11398== Rerun with --leak-check=full to see details of leaked memory
4

3 に答える 3

5

私の思考プロセスはSet *aSet = new Set;、メインクラスでaを使用していて、intはオブジェクトではないため、list.clear()を呼び出しても解放されないというものです。これは正しいですか?メモリを正しく削除するにはどうすればよいですか?

いいえ。正しく割り当てたメモリを削除するには、deleteを呼び出す必要があります。

Set *aSet = new Set;

delete aSet;

ただし、このように手動でメモリを管理することは難しく、エラーが発生しやすくなります。あなたは代替案を好むべきです。1つは、動的割り当てをまったく使用しないことです。単に自動変数を使用する必要があります。

Set aSet;
// no delete required. Variable destroyed/deallocated when it goes out of scope.

本当に動的割り当てが必要な場合は、スマートポインタを使用する必要があります。

std::unique_ptr<Set> aSet(new aSet);

スマートポインタは動的割り当て用にRAIIを実装しているため、手動で行う必要はありません。

まれな状況では、実際に動的割り当てを手動で行う必要がある場合がありますが、これは事前のトピックです。


std::vector<T>::clear()ベクトルのメモリの割り当てを解除する必要はありません。C ++ 11メンバー関数shrink_to_fit()を使用するか、スワップトリックを使用できます。

std::vector<int> list;

...

std::vector<int>(list).swap(list);

また、ベクトルへのポインタを使用するべきではありません。ベクターはRAIIを使用してダイナミックメモリを管理します。ベクトルへのポインタを使用すると、リソースを自分で手動で管理しないという利点がなくなります。

于 2012-11-07T19:38:51.557 に答える
2

実行する前に実行new listする必要がありますdelete list。そうしないと、発見したとおりにメモリリークが発生します。リストを削除する前にリストを作成する必要もありませんclear。デストラクタが自動的にリストをクリアします。編集:Setクラスデストラクタのポインタも削除する必要があります。

listちょっとした話題から外れたヒントですが、組み込み型と間違われる可能性のあるような変数名は使用しないでください。

よりトピックに関するヒントはstd::vector、ポインターの代わりに直接メンバー変数として使用することです。その場合、あなたは間違いなくを使用する必要がありますclear

于 2012-11-07T19:35:38.990 に答える
1

C ++ 11で作業している場合は、shrink_to_fit()を使用できます。私が理解していることから、これは拘束力がなく、実装によって実際に縮小するのを防ぐことができます。

于 2012-11-07T19:35:04.400 に答える