了解你所使用的编程语言究竟是如何实现的,对于C++程序员可能特别有意义。首先,它可以去除我们对于所使用语言的神秘感,使我们不至于对于编译器干的活感到完全不可思议;尤其重要的是,它使我们在Debug和使用语言高级特性的时候,有更多的把握。当需要提高代码效率的时候,这些知识也能够很好地帮助我们。
class X {
int x;
float xx;
public:
X() {}
~X() {}
void printInt() {}
void printFloat() {}
};
| |
|------------------------| <------ X class object memory layout
| int X::x |
|------------------------| stack segment
| float X::xx | |
|------------------------| |
| | \|/
| |
| |
------|------------------------|----------------
| X::X() |
|------------------------| |
| X::~X() | |
|------------------------| \|/
| X::printInt() | text segment
|------------------------|
| X::printFloat() |
|------------------------|
| |
在本示例中
this指针是一个隐含于每一个成员函数中的特殊指针。它是一个指向正在被该成员函数操作的对象,也就是要操作该成员函数的对象。this作用域是在类内部,当对一个对象调用成员函数时,编译程序先将对象的地址赋给this指针,编译器会自动将对象本身的地址作为一个隐含参数传递给函数。也就是说,即使你没有写this指针,编译器在编译的时候也是加上this的,它作为非静态成员函数的隐含形参。被调用的成员函数函数体内所有对类成员的访问,都会被转化为“this->类成员”的方式。
针对第二点,我们类似于:
A x;
x.printInt();
其中,X::printInt()这个行为,在编译器中,将处理为
printInt(const X* this)
那么,x.printInt()调用处理将最终成为
printInt(&x);
class X {
int x;
float xx;
static int count;
public:
X() {}
virtual ~X() {}
virtual void printAll() {}
void printInt() {}
void printFloat() {}
static void printCount() {}
};
其内存布局如下
| |
|------------------------| <------ X class object memory layout
| int X::x |
stack |------------------------|
| | float X::xx |
| |------------------------| |-------|--------------------------|
| | X::_vptr |------| | type_info X |
\|/ |------------------------| |--------------------------|
| o | | address of X::~X() |
| o | |--------------------------|
| o | | address of X::printAll() |
| | |--------------------------|
| |
------|------------------------|------------
| static int X::count | /|\
|------------------------| |
| o | data segment
| o | |
| | \|/
------|------------------------|------------
| X::X() |
|------------------------| |
| X::~X() | |
|------------------------| |
| X::printAll() | \|/
|------------------------| text segment
| X::printInt() |
|------------------------|
| X::printFloat() |
|------------------------|
| static X::printCount() |
|------------------------|
| |
class X {
int x;
string str;
public:
X() {}
virtual ~X() {}
virtual void printAll() {}
};
class Y : public X {
int y;
public:
Y() {}
~Y() {}
void printAll() {}
};
其内存布局信息如下
| |
|------------------------------| <------ Y class object memory layout
| int X::x |
stack |------------------------------|
| | int string::len |
| |string X::str ----------------|
| | char* string::str |
\|/ |------------------------------| |-------|--------------------------|
| X::_vptr |------| | type_info Y |
|------------------------------| |--------------------------|
| int Y::y | | address of Y::~Y() |
|------------------------------| |--------------------------|
| o | | address of Y::printAll() |
| o | |--------------------------|
| o |
------|------------------------------|--------
| X::X() |
|------------------------------| |
| X::~X() | |
|------------------------------| |
| X::printAll() | \|/
|------------------------------| text segment
| Y::Y() |
|------------------------------|
| Y::~Y() |
|------------------------------|
| Y::printAll() |
|------------------------------|
| string::string() |
|------------------------------|
| string::~string() |
|------------------------------|
| string::length() |
|------------------------------|
| o |
| o |
| o |
| |
class X {
public:
int x;
virtual ~X() {}
virtual void printX() {}
};
class Y {
public:
int y;
virtual ~Y() {}
virtual void printY() {}
};
class Z : public X, public Y {
public:
int z;
~Z() {}
void printX() {}
void printY() {}
void printZ() {}
};
内存布局如下
| |
|------------------------------| <------ Z class object memory layout
stack | int X::x |
| |------------------------------| |--------------------------|
| | X:: _vptr |----------------->| type_info Z |
| |------------------------------| |--------------------------|
\|/ | int Y::y | | address of Z::~Z() |
|------------------------------| |--------------------------|
| Y:: _vptr |------| | address of Z::printX() |
|------------------------------| | |--------------------------|
| int Z::z | | |--------GUARD_AREA--------|
|------------------------------| | |--------------------------|
| o | |---------->| type_info Z |
| o | |--------------------------|
| o | | address of Z::~Z() |
| | |--------------------------|
------|------------------------------|--------- | address of Z::printY() |
| X::~X() | | |--------------------------|
|------------------------------| |
| X::printX() | |
|------------------------------| |
| Y::~Y() | \|/
|------------------------------| text segment
| Y::printY() |
|------------------------------|
| Z::~Z() |
|------------------------------|
| Z::printX() |
|------------------------------|
| Z::printY() |
|------------------------------|
| Z::printZ() |
|------------------------------|
| o |
| o |
| |
Y *y_ptr = new Z;
y_ptr->printY(); // OK
y_ptr->printZ(); // Not OK, as virtual table of class Y doesn't have address of printZ() method
( *y_ptr->_vtbl[ 2 ] )( y_ptr )
class X { int x; };
class Y : public virtual X { int y; };
class Z : public virtual X { int z; };
class A : public Y, public Z { int a; };
其布局如下:
| |
Y class ------> |----------------| <------ A class object memory layout
sub-object | Y::y |
|----------------| |------------------|
| Y::_vptr_Y |------| | offset of X | // offset(20) starts from Y
Z class ------> |----------------| |----> |------------------|
sub-object | Z::z | | ..... |
|----------------| |------------------|
| Z::_vptr_Z |------|
|----------------| |
A sub-object --> | A::a | | |------------------|
|----------------| | | offset of X | // offset(12) starts from Z
X class -------> | X::x | |----> |------------------|
shared |----------------| | ..... |
sub-object | | |------------------|
了解内存布局,对我们的项目开发会提供很大的便利,比如对coredump的调试
END
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8