深度探索C++对象模型(11)——数据语义学(1)——数据成员绑定时机、进程内存布局

1.数据成员绑定时机

代码1:

#include <iostream>
using namespace std;

string myvar = "I Love You";  //全局变量myvar

class A
{
public:
	int myfunc();
	//{
	//	return myvar;
	//}

public:
	int myvar;  //局部变量myvar
};

int A::myfunc()
{
	cout << myvar << endl;
	cout << ::myvar.c_str() << endl;
	return myvar;
}

int main()
{
	A a;
	a.myvar = 100;
	cout << a.myfunc() << endl;

}

运行结果:

可以发现不管在类内还是类外定义的类的成员函数,使用的变量名,编译器先从类内优先寻找

而写一个全局函数的话如下:

全局函数解析的myvar是全局变量的myvar

总结:编译器对成员函数myfunc的内部定义解析,是整个A类定义完毕后才开始(如上述代码中int myvar的声明放在成员函数func()的后面,而它却能用到int myvar);因为只有整个类A定义完毕后,编译器参能看到类A中的myvar,才能根据实际的需要把出现myvar的场合做上述的适当的解释(成员函数中解析成类中的myvar,全局函数中解析成全局的myvar)

代码2:

#include <iostream>
#include <time.h >
#include <stdio.h>
using namespace std;

typedef string mytype;

//定义一个类
class A
{
	
public:

	void myfunc(mytype tmpvalue); //string

	typedef int mytype;
private:		
	mytype m_value; //int	
};

void A::myfunc(mytype tmpvalue) //int
{
	m_value = tmpvalue;
}

void myfunc(mytype tmpvalue) //mytype
{
	string mvalue = tmpvalue;
}

可以发现定义在typedef int mytype;之前的函数的参数类型mytype被解析为全局的类型string的别名

可以发现定义在typedef int mytype;之后的成员类型mytype被解析为局部类型int的别名

可以发现定义在typedef int mytype;之后且定义在类外的成员函数的类型mytype被解析为局部类型int的别名

可以发现全局函数的参数类型mytype被解析为全局的类型string的别名

总结:

 对于这种类型定义是在编译器第一次遇到整个类型mytype的时候被决定的;所以,类内定义的函数myfunc中参数类型mytype第一次遇到的时候,编译器只看到了typedef string mytype,没有看到类中的typedef in mytype;而后面的定义都看到了,有限选最近的(优先选当前作用域中的)

为了在类中尽早的看到类型mytype,所以这种类型定义语句typedef,一定 要挪到类的最开头定义。那后边的成员函数第一次遇到这个类型mytype的时候,它就本着最近碰到的类型的原则来应用最近碰到的类型。

2.进程内存布局

    当运行一个可执行文件时,操作系统就会把这个可执行文件加载到内存;此时进程有一个虚拟的地址空间(内存空间)

数据段:存放已经初始化的全局变量或静态变量

BSS段:存放未初始化的全局变量或初始化为0的全局变量

代码演示:

Linux下:

#include <iostream>
#include <time.h >
#include <stdio.h>
using namespace std;

int *ptest = new int(120);
int g1;
int g2;

int g3 = 12;
int g4 = 32;
int g5;
int g6 = 0;
static int g7;
static int g8=0;
static int g9 = 10;
void mygfunc()
{
	return;
}

//定义一个类
class MYACLS
{
public:
	int m_i;
	static int m_si; //声明不是定义
	int m_j;
	static int m_sj;
	int m_k;
	static int m_sk;
	static void myclsfunc() {}
};
int MYACLS::m_sj = 0; //这才是定义;

int main()
{	



	return 1;
}

linux有个nm命令:能够列出可执行文件中的全局变量存放的地址;

剩余晚上更新完

猜你喜欢

转载自blog.csdn.net/qq_34805255/article/details/86635792
今日推荐