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() 然后在向量上删除,但这没有用。然后我尝试擦除(list.begin(),list.end()),但这也没有用。

我的思考过程是我正在使用 Set *aSet = new Set; 在我的主类中,由于 int 不是对象,所以当我调用 list.clear() 时它没有被释放。这是正确的吗?我将如何正确删除内存?

谢谢你的帮助。

Edit1 = 将 list* 更改为 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;在我的主类中使用了一个,因为一个 int 不是一个对象,所以当我调用 list.clear() 时它没有被释放。这是正确的吗?我将如何正确删除内存?

不。要删除您正确分配的内存,您需要调用 delete:

Set *aSet = new Set;

delete aSet;

然而,像这样手动管理内存很困难并且容易出错。你应该更喜欢替代品。首先是您根本不应该使用动态分配。您应该简单地使用自动变量:

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 回答