高分求解,关于C++内存地址的有关问题,不理解

高分求解,关于C++内存地址的问题,不理解!

#include <iostream>
#include <string>
#include <cstdio>
using namespace std;
class People{
public:
int id;
int age;
};
int main(int argc, char **argv) {
    People p1;
    People *p2=new People();
    People p3;
    string str1="Hello";
    char *str2=new char(6);
    printf("%d %d %d\n",&p1,p2,&p3);
    printf("%d %d\n",sizeof(p1),sizeof(p2));
    printf("%d %d\n",&str1,str2);
     printf("%d %d\n",sizeof(str1),sizeof(str2));
return 0;
}


结果:
高分求解,关于C++内存地址的有关问题,不理解
初步的理解是:
1、大小:p2、str2是unsigned类型的指针,所以大小为4,存在于栈中,但他们所指向的连续内存存在于堆中;p1、str1是真正的对象,所以大小等于所包含的field的大小总和,他们是否也存在于栈中,他们所包含的field的内存是否也存在于栈中?
2、地址:输出的&p1、&p3、&str1都是栈内存的地址(由高向低扩展),而p2、str2是堆内存的地址(由低向高扩展);p1、str1是否属于引用类型,还是指针类型?
最好能画个内存结构图给我,高分献上!!!
------解决方案--------------------
最后一行打印sizeof(str1)= 16???为什么??,不应该是4吗
------解决方案--------------------
你的str1是对象, 所以sizeof求的就是对象的大小.

对于1. 
p1、str1是真正的对象,所以大小等于所包含的field的大小总和,他们是否也存在于栈中,他们所包含的field的内存是否也存在于栈中?
field内存在你的代码中是在栈上的, 但是内部保存串的指针就不定是了.

2.p1、str1是否属于引用类型,还是指针类型?
p1,str1都是对象, 不是引用也不是指针.


------解决方案--------------------
p1对像具体是多少应该是取决于编译器. 并不一定正好是成员占用空间相加. 可能有this指针,或者其它东西.
------解决方案--------------------
《深度探索C++对象模型》
《C++反汇编与逆向分析技术揭秘》
------解决方案--------------------
引用:
Quote: 引用:

你的str1是对象, 所以sizeof求的就是对象的大小.

对于1. 
p1、str1是真正的对象,所以大小等于所包含的field的大小总和,他们是否也存在于栈中,他们所包含的field的内存是否也存在于栈中?
field内存在你的代码中是在栈上的, 但是内部保存串的指针就不定是了.

2.p1、str1是否属于引用类型,还是指针类型?
p1,str1都是对象, 不是引用也不是指针.

p1对象在栈中所占用的内存是否是id、age内存的和8?

p1对象在我能想到的绝大多数编译器上都是8,这个this指针毫无关系,事实上,类的大小里就不包含this指针,this指针貌似是语法的概念。不过复杂的类所占空间可能包含虚表,还有基类,还有基类的虚表。但LZ所写的类是最简单的POD类型,不考虑内存对齐,大小就是俩int。考虑了内存对齐,大小还是俩int。
------解决方案--------------------
引用:
Quote: 引用:

Quote: 引用:

Quote: 引用:

你的str1是对象, 所以sizeof求的就是对象的大小.

对于1. 
p1、str1是真正的对象,所以大小等于所包含的field的大小总和,他们是否也存在于栈中,他们所包含的field的内存是否也存在于栈中?
field内存在你的代码中是在栈上的, 但是内部保存串的指针就不定是了.

2.p1、str1是否属于引用类型,还是指针类型?
p1,str1都是对象, 不是引用也不是指针.

p1对象在栈中所占用的内存是否是id、age内存的和8?

p1对象在我能想到的绝大多数编译器上都是8,这个this指针毫无关系,事实上,类的大小里就不包含this指针,this指针貌似是语法的概念。不过复杂的类所占空间可能包含虚表,还有基类,还有基类的虚表。但LZ所写的类是最简单的POD类型,不考虑内存对齐,大小就是俩int。考虑了内存对齐,大小还是俩int。

实际开发中,关于“新建对象”这个代码风格,倾向于p1的写法还是p2的写法呢?

这的看实际情况,一个是堆上的,一个是栈上的。一般来说能放在栈上的当然放在栈上喽,这样不怕内存泄露,而且申请内存的效率远高于new。但现实中总有这样那样的理由,不能放在栈上。
1.栈上的对象生命周期是定死的,出了作用域就没了。正所谓很多时候长处也是短处。
2.栈的空间有限,一般也就几M,稍微分配大点的空间就可以溢出了。
暂时就想到上面俩问题,估计还有其他的原因使得有时候必须new对象。
------解决方案--------------------
vc 2010加选项/d1reportSingleClassLayoutTheString 
#include <string>
#include <cstdio>
class TheString : std::string
{
};

class People{
public:
int id;
int age;
};
int main(int argc, char **argv)
{
People p1;
People *p2=new People();
People p3;
std::string str1="Hello";
char *str2=new char(6);
printf("%p %p %p\n",&p1,&p2,&p3);
printf("%d %d\n",sizeof(p1),sizeof(p2));
printf("%p %p\n",&str1,&str2);
printf("%d %d\n",sizeof(str1),sizeof(str2));
return 0;
}


debug编译输出

ClCompile:
1>  demo.cpp
1>  class TheString size(32):
1>   +---
1>  
------解决方案--------------------
 +--- (base class ?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@)
1>  
------解决方案--------------------
 
------解决方案--------------------
 +--- (base class ?$_String_val@DV?$allocator@D@std@@)
1>  
------解决方案--------------------
 
------解决方案--------------------
 
------解决方案--------------------
 +--- (base class _Container_base12)
1>   0
------解决方案--------------------
 
------解决方案--------------------
 
------解决方案--------------------
 
------解决方案--------------------
 _Myproxy
1>  
------解决方案--------------------
 
------解决方案--------------------
 
------解决方案--------------------