【发布时间】: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