我花了几个小时在一些好的C++书中以及堆栈溢出中寻找对此的讨论,虽然我已经看到了很多关于"堆与堆栈"问题的问题,但我正在寻找更具体地了解在创建类的对象成员时使用或不使用指针, 即与组合。
例如:
class A{
B c;
}
与。
class A{
B*c;
}
在第一个例子中,这不是真正的"堆栈"分配,而是"静态存储区域"中的分配,这是另一回事,所以我认为堆栈与堆的讨论不适用。
我不清楚的是两者的优缺点。似乎我阅读的大多数代码都使用第二个选项,但为什么呢?
可能我不知道这些技术的正确术语来正确搜索这个网站,或者根本没有这方面的问题。如果其他地方确实有与此相关的答案,请务必让我知道如何找到它们,但几乎所有内容似乎都更多地是关于局部变量上下文中的堆栈与堆,我认为我可以处理这个问题。
人们使用第二个选项的原因是:
class A { B b;}; // error, order of classes wrong
class B { };
C++的这个简单特性使得构建具有B b;风格的工作系统变得困难。您必须将所有相关类放在同一个文件中,并将类重新排序为完全正确的顺序。
继承也对顺序产生了一些魔力:
class A : public B { }; // error, order of classes wrong
class B { };
因此,使用继承和 B b; 一起完全固定类的顺序,大量的数据成员将是一场噩梦。(请注意,像 float 和 int 这样的类型没有顺序问题 - 对于类也可以正确执行此操作)
将指向对象的指针作为类的成员的另一个原因是,如果您确实需要它指向某些内容,并且您希望指向的对象经常更改。例如,假设一个类在某个系统或框架(完全虚构)中保留指向活动窗口的指针。下面activeWindow
指向的对象的内存将分配给其他地方,并且指向的对象本身将频繁更改。
class Monitor
{
...
Window* activeWindow
...
}
另一方面,为所有内容提供指针并使用 new
运算符(或 C 中的 malloc()
)手动分配内存往往很慢,因为在堆上分配内存比在堆栈上分配内存慢,并且还需要稍后手动释放。因此,如果可能的话,应该避免这样做。
如果可以取消将对象放在类的存储区域中而不将其分配给堆上,则这样做。
class foo
{
B c;
};
肯定比
class foo
{
public:
foo()
{
this->c = new B();
}
~foo()
{
delete this->c;
}
private:
B* c
};
但话又说回来,这一切都取决于class B
的性质