作者在C ++中解释堆栈和堆时犯了错误还是我误读了一些东西?
这里是代码:
int main() { using namespace std; int nights = 1001; int * pt = new int; // allocate space for an int *pt = 1001; // store a value there cout << "nights value = "; cout << nights << ": location " << &nights << endl; cout << "int "; cout << "value = " << *pt << ": location = " << pt << endl; double * pd = new double; // allocate space for a double *pd = 10000001.0; // store a double there cout << "double "; cout << "value = " << *pd << ": location = " << pd << endl; cout << "location of pointer pd: " << &pd << endl; cout << "size of pt = " << sizeof(pt); cout << ": size of *pt = " << sizeof(*pt) << endl; cout << "size of pd = " << sizeof pd; cout << ": size of *pd = " << sizeof(*pd) << endl; return 0; }
下面是作者关于代码的说明:
另一点需要注意的是,通常new使用与我们一直使用的普通variables定义不同的内存块。 variablesnight和pd都将它们的值存储在称为堆栈的内存区域中,而由new分配的内存位于称为堆栈或自由存储的区域中 。
初始问题:
现在我关心的是:variablespd是由关键字new创build的,所以它应该像variablespt那样存储在heap区域,因为它们都是由关键字new创build的。
我在这里错过了什么? 非常感谢您的投入。
修订问题/根据持有的后续行动:
这个问题被5人搁置,因为他们不明白我在问什么。 我相信我的问题已经得到了答复,但是对于那些还不确定我最初提问的人,请一起阅读:
我不清楚作者对variables及其值存储在内存中的解释。 至于作者的解释,我有一个信念,任何通过使用关键字newdynamic创build的内存(或者我应该在运行时在运行后说)使用关键字new获取存储在堆而不是堆栈 。
所以,当他写到variablespd的值是存储在堆栈中的时候 ,我感到困惑,但是如果这个variables是在关键字new的 “runtime”中创build的,那又怎么可能?所以它应该在堆中 ,而不是堆栈 。
请尝试使用上面的代码作为参考,尤其是您的答案中的**variables(nights,pd和pt ),以便从代码的angular度来理解它。
先谢谢你!
指针variablespt
和pd
存储在堆栈中。 他们指向的值,分配新的,存储在堆上。
如果我写一个标有“湖”的箭头的标志,并不意味着标志本身就是一个湖,也不是说它必须安装在湖中。 相反,它应该安装在坚实的地面,指向湖的方向。
作者犯的唯一错误是
-
一旦使用完指针,就不会调用
delete
。 -
endl
的重复使用是值得怀疑的。 改用\n
。 -
using namespace std;
,而在教程中经常使用,以实现简洁是不适合的生产代码,特别是在标题。 -
使用
int * pt = new int; *pt = 1001;
int * pt = new int; *pt = 1001;
代替int* pt = new int(1001);
由于作者的方式是有问题的,*pt
在两个陈述之间处于不必要的未初始化状态。 这使得你的代码容易陷入不稳定的状态。 -
(次要)。 如果分配失败,你应该总是考虑
new
可能抛出std::bad_alloc
exception的可能性。
我不会担心堆栈和堆太多的条件, 他们是语言实现的概念, 而不是语言本身的一部分。 优先select自动和dynamic存储时间。 这就是C ++标准所使用的,所以为什么要发明一个替代术语的整个负载?
真的,我会烧这本书,给自己一个Stroustrup的副本。
图片将有所帮助。
Automatic storage (stack) Dynamic storage (heap) ------------------------- ---------------------- Item Address Value Address Value ---- ------- ----- ------- ----- nights 0xff001000 1001 pt 0xff001004 0x00b0fff0 ------> 0x00b0fff0 1001 pd 0xff00100c 0x00b0fff4 ------> 0x00b0fff4 10000001.0
对象的nights
, pt
和pd
都有auto
存储时间。 在大多数实现中,这意味着它们是从运行时栈中分配的。 对象nights
住在地址0xff001000
1 0xff001000
储值1001
。 对象pt
位于地址0xff0010004
并存储由new
创build的dynamic对象的地址 ,即0x00b0fff0
。 对象pd
位于地址0xff00100c
并存储由new
创build的另一个dynamic对象的地址,即0x00b0fff4
。
地址0x00b0fff0
和0x00b0fff4
的堆对象0x00b0fff4
存储值1001
和10000001.0
。
编辑
FWIW,我前一段时间写了一个dumper
工具,把对象地址和内容转储出去; 给定的代码
#include <cstdio> #include "dumper.h" using namespace std; int main( void ) { int nights = 1001; int *pt = new int; *pt = 1001; double *pd = new double; *pd = 1000001.0; char *names[] = { "nights", "pt", "pd", "*pt", "*pd" }; void *addrs[] = { &nights, &pt, &pd, pt, pd }; size_t sizes[] = { sizeof nights, sizeof pt, sizeof pd, sizeof *pt, sizeof *pd }; dumper( names, addrs, sizes, 5, stdout ); return 0; }
我得到输出
Item Address 00 01 02 03 ---- ------- -- -- -- -- nights 0x7fff9efe7c6c e9 03 00 00 .... pt 0x7fff9efe7c60 10 20 50 00 ..P. 0x7fff9efe7c64 00 00 00 00 .... pd 0x7fff9efe7c58 30 20 50 00 0.P. 0x7fff9efe7c5c 00 00 00 00 .... *pt 0x502010 e9 03 00 00 .... *pd 0x502030 00 00 00 00 .... 0x502034 82 84 2e 41 ...A
在这种情况下,地址是真实的。 在我的系统(x86_64 / Linux SLES-10)上,堆栈地址从高到低,向下扩展(向低地址),堆地址从低到高,向上扩展(向高地址)。
x86是小端,这意味着寻址的字节是最不重要的字节; 需要从右向左读取多字节对象。
- 所有的地址都是由空气构成的,并不代表任何真实世界的实现或体系结构。
现在我关心的是:variablespd是由关键字new创build的,所以它应该像variablespt那样存储在heap区域,因为它们都是由关键字new创build的。
不,那不是。 代码是:
double * pd = new double; // allocate space for a double
这和以下没有什么不同:
double * pd; pd = new double;
很明显, pd
本身并不是由new
运营商创build的,只有它所拥有的价值。 但他说的是pd
,而不是价值。
pd
variables存储在堆栈内存中,但pd
指向的内存位置在堆内存中分配。 我认为作者想强调这些概念之间的这种差异。