【问题标题】:How to manage member variable in C++如何在 C++ 中管理成员变量
【发布时间】:2010-06-01 15:38:31
【问题描述】:

简而言之,我的问题是关于成员变量作为非托管 C++ 中的指针。

在 java 或 c# 中,我们有“高级指针”。事实上,我们无法察觉其中的“指针”。我们通常这样初始化一个类的成员:

member = new Member();

member = null;

但在 c++ 中,它变得更加混乱。我见过很多样式:使用new,或者将成员变量留在堆栈中。

在我看来,使用boost::shared_ptr 似乎很友好,但在 boost 本身的源代码中到处都有news。这是效率的问题,不是吗?

有没有“尽量避免new”之类的准则?

编辑

我意识到说“将它们留在堆栈中”是不恰当的,这是一种更恰当的说法:当我需要一个 object 作为我的成员变量时,我应该更喜欢 object 而不是 object* ?

【问题讨论】:

  • 不幸的是,我真的不知道你在问什么。是使用函数中声明的变量、原始指针还是智能指针?
  • 它不是“非托管 C++”,它只是 C++,“托管 C++”根本不是 C++——它只是微软的怪物,有点像 C++,但不是 C#。
  • 您不会“将成员变量留在堆栈中”。 “留在堆栈中”的概念在这一点上根本不适用。成员变量驻留在整个对象所在的同一内存中。可以是堆栈,可以是静态内存,也可以是动态内存。
  • @ALL:现在我的观点更清楚了(ps:忘记“非托管C++”,我只是想表达我对“托管”方式的爱)

标签: c++ oop pointers


【解决方案1】:

Boost 源代码不是您应该如何编写源代码的好例子。 Boost 库旨在封装所有繁琐、困难和容易出错的代码,这样您就不必担心代码中的这些问题。

最好的办法是在代码中遵循两条一般规则:

  • 不要在不需要使用指针的地方使用指针
  • 在确实需要使用指针的地方,使用智能指针(如 shared_ptrscoped_ptr

【讨论】:

  • +1 表示“不要在不需要使用指针的地方使用指针”
【解决方案2】:

是的,有一个准则 - 仅在必须时使用动态分配。很多时候你可以而且应该使用值,而不是指针。例如,您应该几乎总是使用:

vector <string> v;

而不是:

vector <string *> v;

并动态分配字符串。

【讨论】:

    【解决方案3】:

    当然,如果您在构造函数中执行一次 new 并在析构函数中执行一次 delete,它当然不会杀死您。在这种简单的情况下,使用智能指针只是毫无意义的开销。

    如果您变得更复杂,或者如果您对异常安全感到偏执,那么智能指针可能是个好主意。

    【讨论】:

      【解决方案4】:
      【解决方案5】:

      使用shared_ptr 的好处是它是一个“智能指针”,不需要显式的delete 来释放内存。否则,如果您使用new,则一旦不再需要该对象,您将不得不显式调用delete 来释放分配的内存。

      【讨论】:

        【解决方案6】:

        在 C++ 中,这是开发人员的选择问题。有更多的权力,但也有更多的责任。

        例子:

        声明具有任意大小内部存储的对象的类。

        1. 如果您将此类设计为在实例化时分配最坏情况的存储,则可以完全避免使用指针。但就平均情况而言,内存使用成本很高。

        2. 如果您将类设计为根据其需要分配内存,您可能会选择使用指针。然后每个实例将只从堆中获取它需要的东西。但是你必须小心避免指针错误。

        3. 如果您将类设计为根据其需要分配内存,您可能仍然能够避免使用内存抽象的指针(即 auto_ptr 或自定义缓冲区方案等)。

          李>

        因此,一个指导方针可能是在应用程序代码中使用裸指针之前探索可用的选项。库代码的平衡可能会有所不同,因为它的范围更有限,可能对性能更敏感,并且(希望)经过更好的测试。

        【讨论】:

          【解决方案7】:

          您可能希望使用 C++ STL 类“autoptr”来管理您的内存。

          另外,在 C++ 中,如果是成员变量,则不一定是指针。

          class MyClass
          {
              MyClass();
          
              MyMember a;
              MyMember* b;
              std::auto_ptr<MyMember> c;
          }
          
          MyClass::MyClass()
          {
              // constructer
              // a is now instantiated -- I don't have to do anything
              b = new MyMember(); // I'll have to delete it in the destructor
              c.reset(new MyMember()); // I won't have to delete it in the destructor
          }
          

          【讨论】:

          • 自己管理内存实际上不是 C++ 中的常见范例。 完全。与 C 相比,C++ 的全部意义在于自己管理内存。
          • 您在考虑托管 C++ 吗?那么,是的,您的评论是正确的。但是,标准 C++ 提供了新的、删除的、STL 分配器来帮助您完成内存管理任务。这篇文章中的 -1 放错了位置。
          • @Lyndsey,相反......在“托管C++”中有垃圾收集,所以你可以随意分配东西而不关心它。因为您必须手动解除分配任何已分配的内容,所以常见的 C++ 风格使用智能指针或 RAII 来自动分配/解除分配,而不是手动分配内容(因为这需要额外的清理工作)。
          • @Michael AS,当你同意某人时,你不会写“相反” :) Manager C++ 确实提供垃圾收集,所以你没有“必须”自己管理内存Konrad Rudolph 的写作方式与普通 C++ 不同,在普通 C++ 中,您经常使用 new 和 delete 等来管理它。
          • @Lyndsey,但我不同意你的看法。当然,C++ 有能力自己管理内存,但这并不意味着它很常见! C++ 还支持资源获取即初始化 (RAII) 的概念,它允许通过使用引用计数智能指针自动分配/解除分配。这比显式使用 new/delete 更常见。
          猜你喜欢
          • 1970-01-01
          • 2013-09-30
          • 2012-04-29
          • 2017-03-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-07-05
          相关资源
          最近更新 更多