我们如何使用重载运算符来防止C ++中的内存泄漏?
任何完整的例子..
此致
PKV
答案 0 :(得分:11)
如果您想避免内存泄漏,请不要使用delete
。
这可能看似矛盾,但事实是手动内存管理容易出错,最好使用自动(或库)技术。
在C ++中,对于您创建的每个对象,应该有明确的所有权。也就是说,您应该能够识别对象的生命周期,可能取决于其他人。
第一步是避免动态内存分配:如果你不使用new
,你就没有什么可以管理的 - 警告:一些库会把你的记忆交给你,期待你释放它。因此,只要有可能,使用堆栈。
使用STL容器(例如new
)而不是滚动自己的情况,可以避免多次使用std::vector<T>
。
第二步是谨慎使用new
,并在分配后立即将内存交给单个所有者。这些所有者包括:
std::unique_ptr
(C ++ 0x)或boost::scoped_ptr
,在最后的手段std::auto_ptr
。boost::ptr_vector
以及Boost.Pointer Container库单个所有者很容易追踪,并且由于对象的生命周期与其所有者相关联,因此对象的生命周期也很容易追踪。
第三步是微妙的,共享所有权的引入。它确实使对象生命周期内的所有推理变得复杂,并且引入了引用循环的风险,这有效地意味着内存泄漏。在某些情况下它们是必需的,但最好尽可能避免。
std::shared_ptr
(C ++ 0x)或同等版本(std::tr1::shared_ptr
,boost::shared_ptr
)std::weak_ptr
(C ++ 0x)或同等的后者用于“打破”循环。但是,即使有关系图,也很难理解在哪里引入weak_ptr
。
修改强>
正如托比亚斯所说,这个成语被称为资源获取初始化(RAII),它被命名为笨拙。一个更新的术语正在出现:用于描述其子集的范围绑定资源管理(SBRM) - &gt;将资源绑定到范围。
答案 1 :(得分:2)
只是为Matthieus回答增加一些更多的一般性:
每当您使用需要释放的资源(内存,网络连接,文件句柄,窗口句柄......)时,请使用Resource Acquisition Is Initialization (RAII)。
这个成语的一个表现形式是上面提到的std :: unique_ptr和boost :: scoped_ptr。 如果您没有可用资源的RAII容器 - 构建一个。这总是值得的。
答案 2 :(得分:2)
大多数人建议使用Boost或STL,但有些情况是不可能的(在操作系统开发,资源有限的嵌入式系统等)。在这种情况下,请确保尽可能使用堆栈,并且只在类的构造函数中使用new
并在其析构函数中使用delete
。对于双重检查,有一些工具可以帮助您查找内存泄漏,例如valgrind
。
答案 3 :(得分:1)
如果您想避免内存泄漏,请不要使用boost.shared_ptr滚动自己的解决方案。如果你真的想手动完成它,那么就把你的清理代码放在析构函数中。