C ++中的堆是否包含类和结构对象,还是仅包含指针?

时间:2019-03-01 14:02:21

标签: c++ heap-memory

我正在阅读Java对象在堆中,但是我想知道C ++或任何编程语言是否也是如此。

4 个答案:

答案 0 :(得分:2)

在这种情况下,

不是C ++语言使用的词。堆是操作系统提供的虚拟内存区域(从非常抽象的高级角度来看)。从C ++中的免费存储区分配的内存通常是由语言实现从堆分配的。这是一个实现细节。

  

C ++中的堆是否包含类...

不。 在C ++中没有存储。它们不包含在内存中。

对象具有存储空间。动态分配的对象存储在空闲存储中,该存储通常在堆内存中。

  

...并构造对象还是仅包含指针?

与类(包括结构)的实例一样,指针也是对象。就像其他类型的对象一样,指针也可以分配在动态,自动或静态(和其他)存储中。


  

我正在阅读Java对象在堆中,但是我想知道C ++是否也是如此...

不。只有动态分配的对象“在堆中”(尽管要注意,这是一个实现细节)。自动存储中的对象“在堆栈上”(虚拟内存的另一个区域,另一个实现细节)。具有静态存储的对象位于内存的另一个区域。

鉴于位置是一个实现细节,对象可能仅存在于处理器的寄存器中,而根本不存在于内存中。

  

...或任何编程语言。

并非所有编程语言都普遍适用。毕竟,我已经告诉您C ++并非如此。除了C ++外,还有其他语言具有不同的存储期限概念。显然,C是另一个例子。

但是您的声明确实适用于许多动态语言。

答案 1 :(得分:0)

在C ++和C中,heap-它是一个abstraction-包含(概念上)内存区域。阅读C dynamic memory allocation上的wikipage(大多数内容也适用于C ++)。在operating system级别,堆由virtual address space中的几个段组成,这些段在运行时增长(通过system calls类似于Linux上的mmap(2),由{{1 }}和/或malloc)。从理论上讲,堆可能不存在或为空(请参见malloc joke-implementation,并将其调整为适用于C ++)。

一个内存区域(它可以在堆中,也可以在call stack上)可以包含一个对象。它还可能包含其他一些聚合(例如数组)。并且还可能包含垃圾(或所有这些垃圾的混合物)。

有时候,一个存储区还没有初始化,那么(那时)它包含了垃圾。例如,::operator new::operator new的结果可以是未初始化的内存。

一个相关且重要的概念是undefined behavior

重要的是对象的storage durationAutomatic variables从概念上讲是在调用堆栈上(在C ++ 11标准n3337中没有提到 ),但是其中一些只是简单地坐在在实践中processor registers中(按as-if rule)。详细了解C ++中的dynamic memory management

Java和C ++之间的重要区别是它们的memory management。 Java语言要求使用garbage collector。但是C ++基于RAII,因此偏爱reference counting(可能被认为是某些不能正确处理circular references的较差的GC技术)和smart pointers

C ++是一种非常困难的编程语言(即使我可以用C ++编写代码,我也并不声称要掌握它)。您将需要数年才能学习C ++。首先阅读一些不错的C++ programming书。另请参见一些C++ reference网站。

我相信垃圾收集的术语和概念甚至对C ++程序员也很有用(因为在某些情况下,您最终将在应用程序中实现专用的GC;请注意{{ 3}})。因此,请阅读Greenspun's tenth rule

答案 2 :(得分:0)

tl; dr在C ++中,变量直接存储在类似于Java的“堆栈”中,但是作为实现细节,它们可以由分配给类似于Java的“堆”中的数据的备份。

我的回答仅适用于常见的C ++实现,不适用于语言本身(例如,我确定嵌入式系统完全不同)。我也忽略了dynamic storage duration(在C ++中使用newdelete关键字所得到的东西),因为在大多数情况下这并不是很有用。

在Java中,您具有堆栈的概念。它保存了基元,并保存了对类的实例的引用(我不会在这里使用“对象”一词,因为it means something very different in C++)。实际的类实例化位于其他地方:在堆上。 Java中的==仅比较堆栈值,而忽略堆值。

同时,在C ++中,当您定义一个类时,例如

class Foo {
  double data;
  std::string more_data;
};

然后实例化

Foo foo = {5.0, "enough data to to prevent the short string optimization from happening"};

然后将Foo的两个数据成员直接放入“堆栈”中。表达式sizeof(Foo)会告诉您Foo的任何实例化需要多少“堆栈”内存(请注意,它始终是相同的,并且是Foo类型的功能,并且不会在运行时不会有所不同。

当然,Foo的{​​{1}}数据成员可以处理任意大小的字符串。为此,典型的std::string实现拥有指向动态分配的内存块的指针。当用非空字符串实例化类型为std::string的变量时,可能会分配该块,然后当该变量超出范围时将其释放(根据Foo的析构函数)。那就是你的“堆”。几乎所有需要存储运行时变化的数据量的东西都将使用“堆”。

答案 3 :(得分:-2)

所谓的堆是程序可以出于任何目的使用的内存。它用于实现对象,存储数据等。