c++对象中的堆栈成员Vs堆成员

Stack members Vs heap members in C++ objects

本文关键字:成员 Vs 堆栈 对象 c++      更新时间:2023-10-16

我提前道歉,因为我不需要一个具体的答案。只要你能给点建议就好了。下面的注释(连同代码)概述了一些观察、澄清和不确定因素。这里的问题实际上是成员的生命周期。

class SomeClass {
 int m_int; // primitive type. hardly ever see a pointer
 // For class instances, you always* seem to see this
 SomeOtherClass* m_some_other_class_instance_1;
 // and not this
 SomeOtherClass m_some_other_class_instance_2;
 // But lately, I've noticed that for std:: templates, it doesn't seem to be this
 vector<double>* m_vector_instance_1;
 // but rather this
 vector<double> m_vector_instance_2;
};
// So it got me thinking ...

void mainThread() {
  SomeClass* some_class_instance_1 = new SomeClass();
  // SomeClass instance on heap
  // So all its members (both <xx>_1 and <xx>_2) are on heap as well
  // Hence all its members will stay alive beyond the scope of this function (or do they?)
  SomeClass some_class_instance_2;
  // SomeClass instance on stack
  // So the only piece of data relating to SomeClass that's on the heap is what's pointed to by <xx>_1 members
  // But everything else will still stay alive within the scope of this function
  // In conclusion, using either case above, members of a SomeClass instance stay alive for their intended period
  // So are <xx>_1 members overkill?
  // Ah, ha, ha, ha, stayin' alive, stayin' alive ...
}

就上下文而言,让我们假设SomeClass不知道它周围的任何其他类,并且现在不期望传入/传出任何东西……因此,构造函数可能只是用whatever初始化其成员,而编写构造函数的人并不知道如何使用该类。唯一关心的是成员是否活着。

我已经通读了这些线程,但它们并不是完全相关的:

为什么我应该使用指针而不是对象本身?

类成员和显式堆栈/堆分配

类成员是对象——指针还是非指针?c++

int m_int; // primitive type. hardly ever see a pointer

如果我看到int *m,我的第一反应是它是一个int型数组。

// For class instances, you always* seem to see this
 SomeOtherClass* m_some_other_class_instance_1;
 // and not this
 SomeOtherClass m_some_other_class_instance_2;

如果需要延迟对象的加载,可能需要对对象进行堆分配,而不是在外部类加载时对其进行构造。这样做的另一个原因可能是出于多态原因。如果SomeOtherClass是你的构造函数中的基类,你可以初始化一个不同的子类。if(some_condition) m_ptr = new Child1(); else m_ptr = new Child2();同样,你可能想把它包装在一个unique_ptr中,这样销毁是自动的,你就不会泄漏了。

 // But lately, I've noticed that for std:: templates, it doesn't seem to be this
 vector<double>* m_vector_instance_1;
 // but rather this
 vector<double> m_vector_instance_2;

如果你持有一个不属于这个类的vector指针,那么ptr就不会是意外的。

堆分配向量(或其他stl容器)没有意义,部分原因是您正在使用它们来消除处理c风格数组和管理内存的痛苦。在vector下面,它将被堆分配。

  SomeClass* some_class_instance_1 = new SomeClass();
  // SomeClass instance on heap
  // So all its members (both <xx>_1 and <xx>_2) are on heap as well
  // Hence all its members will stay alive beyond the scope of this function (or do they?)

是的,它的所有堆栈成员将一直存活直到它被删除。任何堆分配的也必须销毁,如果您正在进行手动分配,请确保调用delete,但最好将unique_ptrshared_ptr1之类的内容包装起来

  SomeClass some_class_instance_2;
  // SomeClass instance on stack
  // So the only piece of data relating to SomeClass that's on the heap is what's pointed to by <xx>_1 members
  // But everything else will still stay alive within the scope of this function

该对象及其成员将在超出作用域时被销毁。虽然它的一些成员是指针。如果它们指向没有其他指针的堆分配成员,则存在内存泄漏。

  // In conclusion, using either case above, members of a SomeClass instance stay alive for their intended period
  // So are <xx>_1 members overkill?

我想不出在上面的上下文中堆分配一个stl容器的正当理由。堆分配其他成员可能是必需的,但在可能的情况下最好不要这样做,即使这样,在可能的情况下也更喜欢使用smart_ptrs

  // Ah, ha, ha, ha, stayin' alive, stayin' alive ...

这是c++,你会慢慢地痛苦地死去。

你的假设实际上是错误的

class SomeClass {
 int m_int; // primitive type. hardly ever see a pointer

不,这取决于上下文或情况,你没有见过的东西并不意味着人们没有使用过。

 // For class instances, you always* seem to see this
 SomeOtherClass* m_some_other_class_instance_1;
 // and not this
 SomeOtherClass m_some_other_class_instance_2;

这里也是一样,这取决于你的要求

 // But lately, I've noticed that for std:: templates, it doesn't seem to be this
 vector<double>* m_vector_instance_1;
 // but rather this
 vector<double> m_vector_instance_2;
};

范围,生命周期是一个不同的术语,它与你是否使用指针无关。

查看这些问题了解更多细节

指针的好处?

https://softwareengineering.stackexchange.com/questions/16211/what-are-use-cases-and-advantages-of-pointers