【问题标题】:Is there a Variable allocated on the Heap?堆上是否分配了变量?
【发布时间】:2019-10-03 09:24:12
【问题描述】:

我有一个关于内存分配主题的测验,这个问题让我很困惑,因为我对答案不满意。 (the Question)

据我所知,我们可以在堆上创建一个“对象”,方法是创建一个指针变量来指向我们在堆上分配的内存(使用@ 987654322@关键字)。

举个具体的例子:

double* a = new double(-1.0f); 

变量a 是一个指针,创建在堆栈 指向堆上的内存。所以实际上,说a 在堆上分配是错误的。我的理解正确吗?

【问题讨论】:

  • 你是对的,a 确实存储在堆栈中。但是从这个角度来看,每个局部变量都存储在堆栈中,只有其中一些可以指向堆。
  • 没错,但是:非正式地,程序员在谈论它指向的对象时经常使用指针变量的名称。它更简单,而且通常从上下文中可以清楚地看到含义。
  • 关于测验:所有这些 变量 确实是“在堆栈上” - 如果测验答案另有说明,那就是错误的(或者问题的措辞不正确)。这个问题显然意味着要问的是不同的(尽管询问对某物的引用是否存在于任何地方有点没有实际意义,并且使整个问题变得混乱)。
  • @Caleth:堆栈指针在函数调用之前移动以将 RSP 对齐 16;这 8 个字节未被使用,RSP 下方的 128 字节红色区域也是如此。您的示例不使用任何变量(保存这些函数调用的结果),所以是的,它们当然会被优化掉。但是,直到下一个call,每个都在RAX 中有效分配,即前一个new 的返回值。优化编译器对 C++ 变量进行寄存器分配,所以是的,取决于您对 a 所做的操作,指针值可能永远不会存储在堆栈内存中。
  • @Caleth:当call _Znwm 返回时,double* var3 在 RAX 中。但是,它是“死的”,因为该变量未使用。编译器甚至可能不会“认为”var3 是 RAX,它可能只是优化了 var3(例如,-fverbose-asm 不会在注释中打印 var3,只是空字符串)。但它必须保持对operator new double() 的调用,因为new 是可替换的,因此调用是可见的副作用。 (泄漏 8 个字节的分配也是如此)。如果你想看点什么,请使用volatile double *var3(它会溢出到内存中)。

标签: c++ memory-management


【解决方案1】:

a 是一个具有自动存储期限的指针。

指向一个double,它具有动态存储持续时间

在丢失指向动态内存的指针之前调用delete a; 是你的工作;通常当a 超出范围时。

(通俗地说,说到C++的典型实现,你可以说a在栈上,它指向堆上的内存。)

【讨论】:

  • 感谢您抽出时间回答我的问题!正如我解释你的回答,正式地,没有在堆上分配的变量这样的东西,只有在堆上分配的内存。对吧?
  • @kevinvu 在形式上,C++ 标准中不存在 stackheap 之类的东西。两者都只是实施问题。一个相关问题:Are there stackless or heapless implementation of C++?.
  • @kevinvu 无论如何,真的没有像在堆上分配的变量这样的东西。 variable 只是一个仅在编译时存在的名称。在运行时,有 objects(某种类型的实例)。对象可以(通过实现)放置在例如堆栈或堆上。在第二种情况下,需要动态分配一些内存,然后需要在那里构造对象。分配和构造是两个不同的东西,销毁和释放也是如此。
【解决方案2】:

你好像明白了。堆*上有一个浮点数,堆栈*上有一个指针。分歧只是你如何引用浮动的命名约定。

有些人用“指向的东西”来谈论“指向的东西”。我倾向于同意你的观点:这可能会造成混淆,并且会增加复杂性。

但是为了公平起见:请记住,不同的人使用语言的方式不同。如果您从不想处理指针并且它们只是让变量在其范围之外持续存在的一种方式,那么将 (*a) 视为变量并记住它遵循略有不同的规则并非完全没有优点。

[*] 模数语法/标准纳粹。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-22
    • 2015-09-11
    • 2020-03-30
    • 2021-04-23
    • 1970-01-01
    • 2015-09-16
    • 2012-11-23
    • 2012-01-18
    相关资源
    最近更新 更多