C++程序运行时内存布局之----------this到底是什么?
2011-07-20 14:20
776 查看
先问一个问题,在C++里,成员函数里的this指针和调用此函数的对象地址总是一样的吗?如果你的回答是:不一定。那么至少你是个老手吧,下面的内容你就不用看了;如果你的回答是:是啊,那么强烈建议你看看下面的内容。
非静态成员函数,无论是不是虚函数,都隐藏了一个this指针参数。这个参数的目的就是给函数提供一个基地址,以便于函数体内能找到对象的成员变量。那非静态成员函数是如何根据this指针找到成员变量的呢?直接看例子吧
1没有虚表的情况
view plaincopy to clipboardprint?#include <iostream>
#include <stdio.h>
using namespace std;
class A
{
public:
int x;
int y;
public:
void F1()
{
this->x = 1;
this->y = 2;
cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;
}
};
int main(int argc, char** argv)
{
A a;
cout<<"a对象的地址是:"<<&a<<endl;
cout<<"a对象的大小是:"<<sizeof(A)<<endl;
cout<<"成员a.x的地址是: "<<&a.x<<endl;
cout<<"成员a.x的偏移是:"<<&A::x<<endl;
a.F1();
cin>>argc;
return 0;
}
此时函数F1的实现伪代码为:
*(this+4+&A::x-1) = 1; //+4是因为存在虚表指针
*(this+4+&A::y-1) = 2; //+4是因为存在虚表指针
程序运行结果如下:
内存布局如下:
结论:this的值和对象地址相同,成员变量偏移量不因虚表指针存在而改变。带虚表的类的成员函数对成员变量的寻址方式不同,增加一个+4。
3单继承的情况
view plaincopy to clipboardprint?#include <iostream>
#include <stdio.h>
using namespace std;
class A
{
public:
int x;
int y;
public:
void F1()
{
this->x = 1;
this->y = 2;
cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;
}
};
class B : public A
{
public:
int z;
public:
virtual void F2()
{
cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;
}
};
int main(int argc, char** argv)
{
B* pb = new B();
cout<<"对象的地址为:"<<std::hex<<std::showbase<<pb<<endl;
pb->F1();
pb->F2();
cin>>argc;
return 0;
}
结果:
内存布局:
再看,如果A,B都有虚函数的情况。
代码:
view plaincopy to clipboardprint?#include <iostream>
#include <stdio.h>
using namespace std;
class A
{
public:
int x;
int y;
public:
virtual void F1()
{
this->x = 1;
this->y = 2;
cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;
}
};
class B
{
public:
int z;
public:
virtual void F2()
{
cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;
}
};
class C : public A, public B
{
public:
int a;
public:
virtual void F2()
{
cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;
}
void F3()
{
cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;
}
};
int main(int argc, char** argv)
{
C* pc = new C();
cout<<"对象的大小为:"<<sizeof(C)<<endl;
cout<<"对象的地址为:"<<std::hex<<std::showbase<<pc<<endl;
cout<<"x的地址"<<&pc->x<<endl;
cout<<"z的地址"<<&pc->z<<endl;
pc->F1();
pc->F2();
pc->B::F2();
pc->F3();
cin>>argc;
return 0;
}
#include <iostream>#include <stdio.h>using namespace std;class A{public:int x;int y;public:virtual void F1(){this->x = 1;this->y = 2;cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;}};class B{public:int z;public:virtual void F2(){cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;}};class C : public A, public B{public:int a;public:virtual void F2(){cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;}void F3(){cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;}};int main(int argc, char** argv){C* pc = new C();cout<<"对象的大小为:"<<sizeof(C)<<endl;cout<<"对象的地址为:"<<std::hex<<std::showbase<<pc<<endl;cout<<"x的地址"<<&pc->x<<endl;cout<<"z的地址"<<&pc->z<<endl;pc->F1();pc->F2();pc->B::F2();pc->F3();cin>>argc;return 0;}
结果:
内存布局:
结论:再一次验证了this指针的值的确定方法,this始终要保证指向定义了该成员函数的类得subobject。因为C++保证base class subobject与base class object完全对应,从而保证了成员函数能根据成员变量在定义了该变量的类中的偏移寻址。
非静态成员函数,无论是不是虚函数,都隐藏了一个this指针参数。这个参数的目的就是给函数提供一个基地址,以便于函数体内能找到对象的成员变量。那非静态成员函数是如何根据this指针找到成员变量的呢?直接看例子吧
1没有虚表的情况
view plaincopy to clipboardprint?#include <iostream>
#include <stdio.h>
using namespace std;
class A
{
public:
int x;
int y;
public:
void F1()
{
this->x = 1;
this->y = 2;
cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;
}
};
int main(int argc, char** argv)
{
A a;
cout<<"a对象的地址是:"<<&a<<endl;
cout<<"a对象的大小是:"<<sizeof(A)<<endl;
cout<<"成员a.x的地址是: "<<&a.x<<endl;
cout<<"成员a.x的偏移是:"<<&A::x<<endl;
a.F1();
cin>>argc;
return 0;
}
view plaincopy to clipboardprint?#include <iostream> #include <stdio.h> using namespace std; class A { public: int x; int y; public: virtual void F1() { this->x = 1; this->y = 2; cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl; } }; int main(int argc, char** argv) { A* p = new A(); cout<<"a对象的地址是:"<<p<<endl; cout<<"a对象的大小是:"<<sizeof(A)<<endl; cout<<"成员a.x的地址是: "<<&p->x<<endl; cout<<"成员a.x的偏移是:"<<&A::x<<endl; p->F1(); cin>>argc; return 0; } #include <iostream>#include <stdio.h>using namespace std;class A{public:int x;int y;public:virtual void F1(){this->x = 1;this->y = 2;cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;}};int main(int argc, char** argv){A* p = new A();cout<<"a对象的地址是:"<<p<<endl;cout<<"a对象的大小是:"<<sizeof(A)<<endl;cout<<"成员a.x的地址是: "<<&p->x<<endl;cout<<"成员a.x的偏移是:"<<&A::x<<endl;p->F1();cin>>argc;return 0;}
此时函数F1的实现伪代码为:
*(this+4+&A::x-1) = 1; //+4是因为存在虚表指针
*(this+4+&A::y-1) = 2; //+4是因为存在虚表指针
程序运行结果如下:
内存布局如下:
结论:this的值和对象地址相同,成员变量偏移量不因虚表指针存在而改变。带虚表的类的成员函数对成员变量的寻址方式不同,增加一个+4。
3单继承的情况
view plaincopy to clipboardprint?#include <iostream>
#include <stdio.h>
using namespace std;
class A
{
public:
int x;
int y;
public:
void F1()
{
this->x = 1;
this->y = 2;
cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;
}
};
class B : public A
{
public:
int z;
public:
virtual void F2()
{
cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;
}
};
int main(int argc, char** argv)
{
B* pb = new B();
cout<<"对象的地址为:"<<std::hex<<std::showbase<<pb<<endl;
pb->F1();
pb->F2();
cin>>argc;
return 0;
}
view plaincopy to clipboardprint?#include <iostream> #include <stdio.h> using namespace std; class A { public: int x; int y; public: void F1() { this->x = 1; this->y = 2; cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl; } }; class B { public: int z; public: virtual void F2() { cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl; } }; class C : public A, public B { public: int a; public: virtual void F2() { cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl; } void F3() { cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl; } }; int main(int argc, char** argv) { C* pc = new C(); cout<<"对象的大小为:"<<sizeof(C)<<endl; cout<<"对象的地址为:"<<std::hex<<std::showbase<<pc<<endl; pc->F1(); pc->F2(); pc->F3(); cin>>argc; return 0; } #include <iostream>#include <stdio.h>using namespace std;class A{public:int x;int y;public:void F1(){this->x = 1;this->y = 2;cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;}};class B{public:int z;public:virtual void F2(){cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;}};class C : public A, public B{public:int a;public:virtual void F2(){cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;}void F3(){cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;}};int main(int argc, char** argv){C* pc = new C();cout<<"对象的大小为:"<<sizeof(C)<<endl;cout<<"对象的地址为:"<<std::hex<<std::showbase<<pc<<endl;pc->F1();pc->F2();pc->F3();cin>>argc;return 0;}
结果:
内存布局:
再看,如果A,B都有虚函数的情况。
代码:
view plaincopy to clipboardprint?#include <iostream>
#include <stdio.h>
using namespace std;
class A
{
public:
int x;
int y;
public:
virtual void F1()
{
this->x = 1;
this->y = 2;
cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;
}
};
class B
{
public:
int z;
public:
virtual void F2()
{
cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;
}
};
class C : public A, public B
{
public:
int a;
public:
virtual void F2()
{
cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;
}
void F3()
{
cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;
}
};
int main(int argc, char** argv)
{
C* pc = new C();
cout<<"对象的大小为:"<<sizeof(C)<<endl;
cout<<"对象的地址为:"<<std::hex<<std::showbase<<pc<<endl;
cout<<"x的地址"<<&pc->x<<endl;
cout<<"z的地址"<<&pc->z<<endl;
pc->F1();
pc->F2();
pc->B::F2();
pc->F3();
cin>>argc;
return 0;
}
#include <iostream>#include <stdio.h>using namespace std;class A{public:int x;int y;public:virtual void F1(){this->x = 1;this->y = 2;cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;}};class B{public:int z;public:virtual void F2(){cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;}};class C : public A, public B{public:int a;public:virtual void F2(){cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;}void F3(){cout<<"this指针得值是:"<<std::hex<<std::showbase<<this<<endl;}};int main(int argc, char** argv){C* pc = new C();cout<<"对象的大小为:"<<sizeof(C)<<endl;cout<<"对象的地址为:"<<std::hex<<std::showbase<<pc<<endl;cout<<"x的地址"<<&pc->x<<endl;cout<<"z的地址"<<&pc->z<<endl;pc->F1();pc->F2();pc->B::F2();pc->F3();cin>>argc;return 0;}
结果:
内存布局:
结论:再一次验证了this指针的值的确定方法,this始终要保证指向定义了该成员函数的类得subobject。因为C++保证base class subobject与base class object完全对应,从而保证了成员函数能根据成员变量在定义了该变量的类中的偏移寻址。
相关文章推荐
- C++程序运行时内存布局之----------this到底是什么?
- C++程序运行时内存布局之----------this到底是什么?
- C++程序运行时内存布局之----------this到底是什么?
- C++程序运行时内存布局之----------this到底是什么?
- C++程序运行时内存布局之----------this到底是什么?
- C++程序运行时内存布局之----------this到底是什么?
- C++程序运行时内存布局之----------this到底是什么?
- C++程序运行时内存布局之----------this到底是什么?
- C++程序运行时内存布局之----------this到底是什么
- C++程序运行时内存布局之----------简单类实例,成员变量,成员函数,静态成员变量,静态成员函数
- C++程序运行时内存布局之----------无继承情况下的虚函数
- C++程序运行时内存布局之----------无继承情况下的虚函数
- C++程序运行时内存布局之----------简单类实例,成员变量,成员函数,静态成员变量,静态成员函数
- C++程序运行时内存布局之----------局部变量,全局变量,静态变量,函数代码,new出来的变量
- C++程序运行时内存布局之----------空类实例
- C++程序运行时内存布局之----------简单类实例,成员变量,成员函数,静态成员变量,静态成员函数
- C++程序运行时内存布局
- C++程序运行时内存布局之----------无继承情况下的虚函数
- C++程序运行时内存布局之----------局部变量,全局变量,静态变量,函数代码,new出来的变量
- C++程序运行时内存布局之----------局部变量,全局变量,静态变量,函数代码,new出来的变量