【发布时间】:2011-03-22 16:18:37
【问题描述】:
我们如何使用重载运算符来防止 C++ 中的内存泄漏?
任何完整的例子..
问候,
PKV
【问题讨论】:
-
好吧,我想您可能会使操作员过载,从而导致系统关闭或发生其他情况。你有一个特定的场景吗?
-
你的意思是使用重载的
operator new?
标签: c++ memory memory-leaks
我们如何使用重载运算符来防止 C++ 中的内存泄漏?
任何完整的例子..
问候,
PKV
【问题讨论】:
operator new?
标签: c++ memory memory-leaks
如果要避免内存泄漏,请不要使用delete。
这可能看起来自相矛盾,但事实是手动内存管理容易出错,最好使用自动(或库)技术。
在 C++ 中,对于您创建的每个对象,都应该有一个明确的所有权。也就是说,您应该能够识别对象的生命周期,这可能取决于其他一些。
第一步是避免动态内存分配:如果你不使用new,你就没有任何东西需要管理——警告:一些库会把内存交给你并期望你释放它。因此,尽可能使用堆栈。
使用 STL 容器(例如 std::vector<T>)可以避免多次使用 new,而不是滚动您自己的情况。
第二步是谨慎使用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,即使有关系图也是如此。
编辑:
正如 Tobias 所指出的,这个习语被称为 Resources Acquisition Is Initialization (RAII),这个名字很尴尬。一个较新的术语正在出现:范围绑定资源管理 (SBRM) 来描述它的一个子集 --> 将资源绑定到一个范围。
【讨论】:
make_shared 和allocate_shared,让您也可以避免使用new。
new。
new。还应注意placement new 也可以安全使用而不会导致内存泄漏。
只是为了给 Matthieus 的回答增加一些通用性:
每当您使用需要释放的资源(内存、网络连接、文件句柄、Windows 句柄等)时,请使用Resource Acquisition Is Initialization (RAII)。
这个习语的一个表现形式是上面提到的 std::unique_ptr 和 boost::scoped_ptr。 如果您没有可用的所需资源的 RAII 容器 - 构建一个。这总是值得的。
【讨论】:
大多数人建议使用 Boost 或 STL,但在某些情况下这是不可能的(在操作系统开发、资源有限的嵌入式系统等)。在这种情况下,请确保尽可能使用堆栈,并且只在类的构造函数中使用new,在其析构函数中使用delete。对于双重检查,有一些工具可以帮助您发现内存泄漏,例如 valgrind。
【讨论】:
如果您想避免内存泄漏,请不要推出自己的解决方案,请使用boost.shared_ptr。如果您真的想手动执行此操作,请将清理代码放入析构函数中。
【讨论】: