Visual C ++本机内存管理最佳实践

时间:2011-02-10 22:47:47

标签: c++ visual-c++ memory-management

我是一名老C#程序员和C程序员(没有动态内存分配),但想了解一下Visual C ++编程。困扰我的问题与C ++中的内存管理有关。在C#中,垃圾收集器负责内存管理,但在C ++中,有必要建立一些关于谁负责释放分配的内存的规则。我有一些来自C#的典型场景:

  1. 将对象放入某种容器中。谁负责释放记忆。如果几个类共享同一个对象怎么办?

  2. 工厂模式。我喜欢使用类的层次结构,其中父类有一个创建子对象的方法?

  3. 有没有办法向调用方法建议返回的对象是被调用者/调用者的所有权。

  4. 我想听听一些有关此问题的好建议。

2 个答案:

答案 0 :(得分:12)

如果您正确编写代码,则不必担心这一点,至少不要直接担心。您可以使用图书馆工具,完全自动地为您处理内存管理和其他资源管理,这样您就不必这样做了。

C ++提供了比垃圾收集器好得多的东西:它提供了对所有对象的确定性破坏,并且确定性破坏可以用于自动管理每个资源的生命周期,不像垃圾收集(在许多常见的实现中)只允许你自动管理内存并使您手动管理需要确定性清理的所有其他资源。

如果动态分配对象,请使用智能指针管理其生命周期。如果您不需要共享所有权,那么您可以使用std::unique_ptr,这允许您将所有权从一个所有者转移到另一个。如果您确实需要共享所有权,则可以使用std::shared_ptr,它使用引用计数技术来维护共享所有权。

要记住两条重要规则:

  • 如果你必须在C ++程序中编写delete,那么代码几乎肯定是错误的。 C ++为所有资源(包括内存)提供自动生命周期管理,你应该利用它。应该出现的唯一地方delete位于库代码中,其中实现了资源拥有容器,并且可能是稀有的低级代码。

  • 希望尽可能处理对象,而不是指向对象的指针。尽可能避免显式动态分配。 C ++不像C#和Java这样的语言,大多数对象都是在堆上创建的。在C ++中通常更好的是在堆栈上创建对象(使用自动变量)并按值返回它们。

回答您的具体情况:

  

将对象放入某种容器中。谁负责释放记忆。如果几个类共享同一个对象怎么办?

您应该尽可能将对象本身存储在容器中,而不是指向对象的指针。如果由于某种原因需要存储指向对象的指针,则应使用容器(例如std::vector)智能指针。如果容器拥有动态分配的对象的唯一所有权,则可以使用std::vector<std::unique_ptr<T>>;如果容器要共享对象的所有权,则可以使用std::vector<std::shared_ptr<T>>

  

工厂模式。我喜欢使用类的层次结构,其中父类有一个创建子对象的方法?

这与前一个场景没有什么不同:如果你有一棵树,那么使用std::vector<T>(或std::vector<std::unique_ptr<T>>如果你需要动态分配的孩子)来拥有孩子是非常简单的。< / p>

  

有没有办法向调用方法建议返回的对象是被调用者/调用者的所有权。

如果对象完全由被调用者拥有(例如在std::unique_ptr中),则可以返回该智能指针;这样做会将所有权转移给来电者。

如果对象的共享所有权(例如在std::shared_ptr中),则返回智能指针将使调用者成为所有者之一;放弃其所有权的最后一个所有者(通过销毁或以其他方式重置拥有该对象的std::shared_ptr)会自动销毁该对象。

答案 1 :(得分:3)

詹姆斯的回答是正确的。但是,他没有提到他正在讨论的技术的名称。 RAII是C ++中内存(和其他资源)管理的一个非常重要的概念。 RAII代表资源获取是初始化。但是,不要让这个名字混淆你,因为它有点误导。

维基百科是一个开始阅读的好地方: RAII on Wikipedia