我在过去的几天里痛苦地学习了很多关于c ++编程的知识
我喜欢它:)
我知道我应该释放记忆 - 现在我的世界中存在着金色的“每个malloc = free”或“每个new = delete”规则,但我将它们用于相当简单的对象。
矢量怎么样?无论我在哪里,我都在使用vector.clear(),但这显然是不够的,因为我有大量的内存泄漏。
你能指导我如何对待这件事吗?
*编辑
谢谢,你的评论让我想到了这个应用程序的算法,我将能够完全消除向量。 :o
对不起 - 我开始在这里解释我的用例是什么,我发现了我真正需要的东西。就像每天18小时编码最后3天一样:|
*编辑2
这太疯狂了。通过代码的微小变化,我将内存使用量从2x130 mb(不断增长)消除到2x 13,5mb,恒定大小。谢谢你让我以另一种方式思考这个问题。
顺便说一下。这样的自我代码审查有一个名字 - 有人记得吗?当你问任何人(甚至你的母亲或狗)并开始解释你的问题时 - 突然你自己解决了这个5小时的问题,只是试图从其他角度来看待它,或者只是试图总结它是什么所有关于。我经常发现自己被抓住了......
答案 0 :(得分:22)
规则是当你清除一个对象向量时,将调用每个元素的析构函数。另一方面,如果你有一个指针向量,vector::clear()
将不会在它们上面调用delete
,你必须自己删除它们。
因此,如果你拥有的是一个字符串向量,而不是指向字符串的指针,那么你的内存泄漏必须由其他东西引起。
答案 1 :(得分:9)
你不需要这样做。 std :: string清理自己,所以字符串不是你的问题。请记住,您没有使用new
,因此您不必使用delete
。
您应该了解RAII - 它使分配和释放更加简单。你会以这种方式避免内存泄漏。
答案 2 :(得分:7)
调用v.clear()
将销毁当前保存在v
内的所有对象,但它不会释放内存(假设该向量很快将再次填充)。
如果你真的想释放记忆,那么成语就是
vector<string>().swap(v);
这将创建一个新的(临时)向量,并将其内容与v
交换。然后销毁临时矢量,释放内存。
答案 3 :(得分:5)
向量(与所有标准容器一样)拥有其中的对象 所以它负责摧毁它们。
注意:如果vector包含指针,那么它拥有指针(而不是指针指向的指针)。所以这些都需要删除。但是有更简单的方法。
您可以使用智能指针向量。事实上,你应该使用某种形式的智能指针几乎所有东西。如果你使用指针,你可能仍然像C程序员一样编程。
所以:
std::vector<int> data; // clear is fine.
std::vector<int*> data1; // Now things need to be deleted.
// alternative 1:
std::vector<boost::shared_ptr<int> > data2; // The shared pointer will auto
// delete the pointer.
// alternative 2:
boost::ptr_vector<int> data3; // Here the container knows that
// it is holding pointers and will
// auto de-reference them when you
// its members.
但听起来你需要开始考虑学习智能指针。
int* x = new int(5);
// Do stuff.
*x = 8;
delete x;
// --- Instead use a smart pointer:
std::auto_ptr<int> x(new int(5));
// Do stuff.
*x = 8;
// No delete (the auto ptr handles it.
答案 4 :(得分:5)
保证从STL容器中删除元素可以在这些元素上调用析构函数。
但是,如果你有一个pointer-to-T
类型的容器,那么你仍然必须自己释放指向内存(在这种情况下,指针的“析构函数”被调用,这是一个无操作)
如果您不想在这种情况下手动管理内存,请考虑使用smart-pointer solution或pointer container。
答案 5 :(得分:2)
如果你有一个向量并且它超出范围,则向量中的所有对象都将被销毁。除非您想要转储内容并重用向量,否则不需要调用clear()。
但是,如果您有任何机会使用类似向量的东西,那么指向的对象的析构函数将不会被调用,因为向量析构函数不遵循指针所代表的间接。
所有这一切,你真的确认你有真正的内存泄漏,并且它们是由向量中的数据引起的吗?
答案 6 :(得分:0)
提供一个用例。字符串上的析构函数被vector :: clear调用。你的问题出在我朋友的其他地方。
也请查看:
Does std::vector.clear() do delete (free memory) on each element?
答案 7 :(得分:0)
正如rlbond所建议的那样,使用RAII。
从不将新的和删除调用放入主代码流中是一个很好的经验法则。总是尝试将它们放入对象中,以便对象析构函数可以释放需要释放的内容。通过这种方式,您可以避免需要记住调用delete并使代码异常安全(假设您使对象的操作异常安全)。
例如,如果您有一个指向STL字符串或C样式字符数组的指针向量,请将其放入StringContainer(使用更好的名称)并让StringContainer保存一个向量,并在StringContainer析构函数中运行for循环删除向量中的每个字符串。
你可以使StringContainer中的向量成为一个公共成员并直接使用它,但更好的设计是将其设为私有或受保护,并添加一些成员函数来管理字符串*向量。
所以你的主要C ++程序永远不应该在任何地方看到新的或删除。相反,它应该有很多堆栈分配的对象,auto_ptrs和shared_ptrs。