在 C++ 的上下文中(没关系):
class Foo{
private:
int x[100];
public:
Foo();
}
我所学到的告诉我,如果你像这样创建一个 Foo 实例:
Foo bar = new Foo();
然后数组 x 分配在堆上,但是如果您像这样创建 Foo 的实例:
Foo bar;
然后它在堆栈上创建。
我在网上找不到资源来确认这一点。
在 C++ 的上下文中(没关系):
class Foo{
private:
int x[100];
public:
Foo();
}
我所学到的告诉我,如果你像这样创建一个 Foo 实例:
Foo bar = new Foo();
然后数组 x 分配在堆上,但是如果您像这样创建 Foo 的实例:
Foo bar;
然后它在堆栈上创建。
我在网上找不到资源来确认这一点。
对您的示例稍作修改:
class Foo{
private:
int x[100];
int *y;
public:
Foo()
{
y = new int[100];
}
~Foo()
{
delete[] y;
}
}
示例 1:
Foo *bar = new Foo();
示例 2:
Foo bar;
由于类/结构对齐,实际大小可能略有不同,具体取决于您的编译器和平台。
严格来说,根据标准,对象不必存在于堆栈或堆中。该标准定义了 3 种类型的“存储持续时间”,但没有明确说明必须如何实现存储:
自动存储持续时间通常(几乎总是)使用堆栈实现。
动态存储持续时间通常使用堆(最终通过malloc()
)实现,尽管即使编译器的用户也可以覆盖它。
静态存储持续时间通常称为全局(或静态存储)。
该标准对这些事情有这样的说法(以下是 3.7 - 存储持续时间的各个部分的摘录):
静态和自动存储持续时间与由声明 (3.1) 引入并由实现 (12.2) 隐式创建的对象相关联。动态存储持续时间与使用 operator new (5.3.4) 创建的对象相关联。
...
所有既不具有动态存储持续时间也不是本地对象的对象具有静态存储持续时间。这些对象的存储应持续到程序的持续时间(3.6.2、3.6.3)。
...
显式声明 auto 或 register 或未显式声明 static 或 extern 的本地对象具有自动存储持续时间。这些对象的存储一直持续到创建它们的块退出。
...
对象可以在程序执行期间动态创建 (1.9),使用 new-expressions (5.3.4),并使用 delete-expressions (5.3.5) 销毁。AC++ 实现通过全局分配函数 operator new 和 operator new[] 以及全局解除分配函数 operator delete 和 operator delete[] 提供对动态存储的访问和管理。
...
该库为全局分配和释放函数提供默认定义。一些全局分配和释放函数是可替换的 (18.4.1)
最后(关于示例类中的数组):
3.7.4 子对象的持续时间 [basic.stc.inherit]
成员子对象、基类子对象和数组元素的存储时间是它们完整对象的存储时间(1.8)。
Foo 类型的对象按顺序存储 100 个整数的大小。如果你在堆栈上创建它,你将把它全部放在堆栈上。如果您使用 new 执行此操作,它将作为对象的一部分在堆上。
这是语言规范的一部分,我不确定你的问题是什么。
是的,如果在堆上创建对象,成员数组x
将在堆上创建。Foo
当您为您分配动态内存时,Foo
您要求的内存长度sizeof(Foo)
(可能还有一些内存开销,但我们暂时忽略它),这在您的示例代码中意味着 100int
秒的大小。这必须是类型对象Foo
(及其内部数据)的生命周期跨范围的情况。
如果您不在Foo
堆上创建对象,并且内部数组Foo
不是您使用new
inFoo
的构造函数分配内存的指针,则将在堆栈上创建该内部数组。delete
同样,必须如此,才能在作用域结束时自动清理数组而无需任何s。具体来说,
struct Foo {
int* y;
Foo() : y(new int()) { }
~Foo() { delete y; }
};
y
无论Foo
对象是在堆栈上还是在堆上创建,都将在堆上创建。
你的意思是
Foo* bar = new Foo();
我想。那是在堆中创建的。