类的内存分配以及通过内存创建对象
word版下载
1.需要论证的观点
1.1 类的类型的大小= 成员变量的大小的总和,与成员函数无关。即
1.2 成员函数存放在代码段,且不能被改变。对象只为成员变量在栈或堆上分配空间(不考虑virtual和继承等复杂点的情况)
1.3 可以把栈或堆上的某个内存地址转化成(指向类的)指针,如果该内存区域恰好符合该类的对象的内存布局,那么这个指针就可以调用该类的方法了。【本文的重点】
2. 例程
2.1 例程1
#include <stdio.h> #include <iostream> using std::cout; using std::endl; class Base { public: Base(int _age = 100, int _height = 200, int _length = 300) : age(_age), height(_height), length(_length) {} ~Base() {}
void print() { cout<<"age="<<age<<endl; cout<<"height="<<height<<endl; cout<<"length="<<length<<endl; }
size_t get_size() { return sizeof(age) + sizeof(height) + sizeof(length); } private: int age; int height; int length; }; int main(int argc, char *argv[]) { Base a; cout<<"\tsizeof(class Base) ="<<sizeof(class Base)<<endl; cout<<"\tsizeof(a) ="<<sizeof(a)<<endl; cout<<"\tget_size() ="<<a.get_size()<<endl; cout<<"conclusion: sizeof(class T) == sizeof(t) == sizeof(variable0) + sizeof(variable1) + ...... + szieof(variableN)"<<endl; return 0; }
结果
sizeof(class Base) =12
sizeof(a) =12
get_size() =12
conclusion: sizeof(class T) == sizeof(t) == sizeof(variable0) + sizeof(variable1) + ...... + szieof(variableN)
结论
2.2 例程2
#include <stdio.h> #include <iostream> using std::cout; using std::endl; class Base { public: Base(int _age = 100, int _height = 200, int _length = 300) : age(_age), height(_height), length(_length) {} ~Base() {} void print() { cout<<"content:"<<endl; cout<<"\tage ="<<age<<endl; cout<<"\theight ="<<height<<endl; cout<<"\tlength ="<<length<<endl; int *p = &length; cout<<"\t *(p+1)="<<*(p+1)<<"\tthe next content of length"<<endl; } void print_address() { cout<<"address:"<<endl; cout<<"\tthis ="<<this<<endl; cout<<"\t&age ="<<&age<<endl; cout<<"\t&height ="<<&height<<endl; cout<<"\t&length ="<<&length<<endl; cout<<"\t--------------"<<endl; cout<<"Code Segment address:"<<endl; printf("\t&Base::print =%p\n", &Base::print); printf("\t&Base::print_address=%p\n", &Base::print_address); } private: int age; int height; int length; }; int main(int argc, char *argv[]) { Base a; a.print(); cout<<endl; a.print_address(); printf("\tmain =%p\n", main); //write into Code Segment void *pf = (void*)&Base::print; int *pfun = (int*)pf; *pfun = 1;//Segmentation fault return 0; }
结果
content:
age =100
height =200
length =300
*(p+1) =134515771 the next content of length
栈stack
address:
this =0xbfea383c
&age =0xbfea383c
&height =0xbfea3840
&length =0xbfea3844
--------------
Code Segment address:代码段
&Base::print = 0x804896c
&Base::print_address = 0x8048a90
main = 0x8048830
Segmentation fault (core dumped)//因为代码段是只读的,所以不能写
结论
内存分布如图所示
2.3 例程3
#include <stdio.h> #include <iostream> #include <typeinfo> using std::cout; using std::endl; class Base { public: Base(int _age = 100, int _height = 200, int _length = 300) : age(_age), height(_height), length(_length) {} ~Base() {} void print() { cout<<"-->Base::print()"<<endl; cout<<"\tage ="<<age<<endl; cout<<"\theight="<<height<<endl; cout<<"\tlength="<<length<<endl; cout<<"<--Base::print()"<<endl; } private: int age; int height; int length; }; int main(int argc, char *argv[]) { Base *bp = new Base(); bp->print(); cout<<"********************************************"<<endl; cout<<"create Base by new int[3]"<<endl; cout<<"********************************************"<<endl; int *pi = new int[3]; pi[0] = 400; pi[1] = 500; pi[2] = 600; Base *bp2 = (Base*)pi; //该内存区域的首地址转换成指向Base的指针 bp2->print();//调用Base的方法 return 0; }
结果
-->Base::print()
age =100
height =200
length =300
<--Base::print()
********************************************
create Base by new int[3]
********************************************
-->Base::print()
age =400
height =500
length =600
<--Base::print()
结论
通过手动构造一块内存区域,然后把该内存区域的首地址转换成指向Base的指针,就可以调用Base的方法了。
作者:loverszhaokai
出处:http://www.cnblogs.com/lovers
本文采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。