这是代码:
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;
}
Run Code Online (Sandbox Code Playgroud)
现在这里是作者关于代码的说明:
需要注意的另一点是,通常new使用不同的内存块,而不是我们一直使用的普通变量定义.变量nights和pd都将其值存储在称为堆栈的内存区域中,而new分配的内存位于称为堆或自由存储的区域中.
初步问题:
现在我担心的是:变量pd是由关键字new创建的,因此它应该像变量pt一样存储在名为heap的区域中,因为它们都是由关键字new创建的.
我在这里错过了什么吗?非常感谢您的投入.
基于搁置的修订问题/后续行动:
这个问题被5个人搁置了,因为他们无法理解我在问什么.我相信我的问题已经得到了回答,但对于那些仍然不确定我最初要求的人,请继续阅读:
我不清楚作者关于变量及其值存储在内存中的位置的解释.至于作者的解释,我有一种信念,即通过使用关键字new动态创建的任何内存(或者我应该在编译后的运行时说)都存储在堆中而不是堆栈中.
因此,当他写出变量pd具有存储在堆栈中的值时,它让我很困惑,但是如果变量是在"runtime"期间使用关键字new创建的,那么它是如何可能的,所以它应该在堆中,而不是堆栈.
请尝试使用上面的代码作为参考,特别是答案中的**变量(nights,pd和pt),以便从代码的角度理解它.
先感谢您!
Lun*_*din 96
指针变量pt和pd存储在堆栈上.它们指向的值(用new分配)存储在堆上.
如果我写一个带有标有"湖"的箭头的标志,那并不意味着标志本身就是一个湖泊,也不是说它必须安装在湖中.相反,它应该安装在坚实的地面上,指向湖的方向.
Bat*_*eba 19
作者唯一的错误是
delete一旦使用指针就不会调用.
重复使用endl是值得怀疑的.请\n改用.
using namespace std;虽然经常在教程中用来实现简洁,但在生产代码中却是不明智的,特别是在标题中.
int * pt = new int; *pt = 1001;代替使用int* pt = new int(1001);是有问题的,因为作者拥有它的方式,*pt在两个陈述之间处于不必要的未初始化状态.这使得您的代码容易受到不稳定性的影响.
(次要).如果分配失败,您应该始终考虑可能new抛出std::bad_alloc异常的可能性.
我不会担心术语堆栈和堆太多; 它们是语言实现概念,不是语言本身的一部分.首选术语自动和动态存储持续时间.这就是C++标准所使用的,那么为什么要发明一整套替代术语呢?
我真的把这本书烧掉了,给自己一份Stroustrup.
Joh*_*ode 16
图片会有所帮助.
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
Run Code Online (Sandbox Code Playgroud)
对象nights,pt以及pd所有对象都有auto存储持续时间.在大多数实现中,这意味着它们是从运行时堆栈中分配的.对象nights位于地址0xff0010001并存储该值1001.对象pt住在地址0xff0010004并存储该地址由创建的动态对象的new,这是0x00b0fff0.该对象pd位于地址0xff00100c并存储由其创建的另一个动态对象的地址new,即0x00b0fff4.
堆对象在地址处0x00b0fff0并分别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;
}
Run Code Online (Sandbox Code Playgroud)
我得到了输出
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
Run Code Online (Sandbox Code Playgroud)
在这种情况下,地址是真实的.在我的系统(x86_64/Linux SLES-10)上,堆栈地址从高位开始"向下"(向低位地址)增长,而堆地址从低位开始向上增长(朝向更高地址).
x86是小端,意味着被寻址的字节是最低有效字节; 需要从右到左读取多字节对象.
Dav*_*rtz 15
现在我担心的是:变量pd是由关键字new创建的,因此它应该像变量pt一样存储在名为heap的区域中,因为它们都是由关键字new创建的.
不,那不是.代码是:
double * pd = new double; // allocate space for a double
Run Code Online (Sandbox Code Playgroud)
这与以下内容没有区别:
double * pd;
pd = new double;
Run Code Online (Sandbox Code Playgroud)
很明显,pd它本身不是由new运营商创造的,只有它所拥有的价值.但他在谈论pd,而不是它的价值.