81 C++对象模型探索。数据语义学 - 静态成员变量的存取,非静态成员变量的存取

一,静态成员变量的存取

静态成员变量只有一个实体,保存在可执行文件的数据段中,如果没有初始化则保存在数据段的BBS中,由于存储在执行文件的数据段中,因此在编译阶段就会确定地址。当程序编译完成后,不管运行多少次,都是一个地址

静态成员变量:可以当做一个全局变量,但是他只在类的空间内可见,引用时用 类名::静态成员变量名

//为了方便查看 反汇编 的代码都执行了些啥,直接将这三行裸体的放在这里,发现其反汇编的代码是一样的,因此说这三种方式是一样的。
    Teacher7::m_si  = 888888;
008FCA12  mov         dword ptr [Teacher7::m_si (0905000h)],0D9038h  
    tea.m_si  = 999999;
008FCA1C  mov         dword ptr [Teacher7::m_si (0905000h)],0F423Fh  
    ptea->m_si  = 888999;
008FCA26  mov         dword ptr [Teacher7::m_si (0905000h)],0D90A7h  

class Teacher7 {
public:
	int m_i;
	static int m_si;//只是声明,没有定义,因此不分配空间。
	int m_j;
	static int m_sj;
	int m_k;
	static int m_sk;
	char m_c;
	int m_n;
};

int Teacher7::m_si = 999;

void main() {
	//静态成员的访问和赋值,如下的三种方式都一样的,可以通过查看汇编来证明
	cout << Teacher7::m_si << endl;
	Teacher7 tea;
	Teacher7* ptea = new Teacher7();
	cout << tea.m_si << endl;
	cout << ptea->m_si << endl;

	Teacher7::m_si = 888;
	cout << Teacher7::m_si << endl;
	cout << tea.m_si << endl;
	cout << ptea->m_si << endl;

	tea.m_si = 777;
	cout << Teacher7::m_si << endl;
	cout << tea.m_si << endl;
	cout << ptea->m_si << endl;

	ptea->m_si = 666;
	cout << Teacher7::m_si << endl;
	cout << tea.m_si << endl;
	cout << ptea->m_si << endl;

	//为了方便查看 反汇编 的代码都执行了些啥,直接将这三行裸体的放在这里
	Teacher7::m_si  = 888888;
	tea.m_si  = 999999;
	ptea->m_si  = 888999;

	cout << "duandian" << endl;
}

二,非静态成员变量的存储

静态成员变量的存储(普通的成员变量),存放在类的对象总,存取通过类对象,或者类对象指针完成。具体来说是分为:通过类对象的成员函数访问,通过类对象指针的成员函数访问,类对象直接访问,类对象指针直接访问。

这个比较简单,我们就不写例子了。

要注意的是,对于普通成员的访问,编译器本质是 通过:

类对象的首地址 + 成员变量的偏移量     来访问的。

如下图。

我们还可以得出一个结论:在没有虚函数的情况下,在没有父类的情况下:

&Teacher 的值  和 第一个变量的地址是一样的。 

81 C++对象模型探索。数据语义学 - 静态成员变量的存取,非静态成员变量的存取_第1张图片

在通过成员函数访问成员变量的时候,编译器角度是加上了一个 Teacher * const this的指针。

但是有虚基类的时候,会有不同,后边会讲到。

你可能感兴趣的:(c++)