CONST:
int me;
const int* p1 = &me;
//p1可变,*p1不可变,此时不能用*p1来修改,但是p1可以转向
int
* const p2 = &me;
//p2不可变,*p2可变,此时允许*p2来修改其值,但是p2不能转向。
const int* const p3 = &me;
//p3不可变,*p3也不可变,此时既不能用*p3来修改其值,也不能转向
内联函数:
宏:就是使用一个字符串来代替一个表达式代码或函数调用代码;编译之前,预处理器会使用这个宏字符串所代表的表达式代码或函数调用代码来替换所有出现的宏字符串,这样的话,用宏表示的函数调用代码就不用另外开辟函数栈,不用保护和恢复函数调用现场,这样就提高了代码的执行效率;所以,调用一个宏比调用一个函数更有效;
但是调用宏的时候,有一个缺点:由于宏在预处理时使用的是宏字符串替换,所以,编译器在编译的时候不知道宏所代表的代码的语法,不知道宏所代表的代码的数据类型,没有安全检查;如果出现的类里面,宏不能访问类的私有成员,而且容易产生二意性;所以,宏也有自己不能解决的、不可避免的问题;
解决宏定义函数所带来的问题的办法,就是使用内联函数;可以使用内联函数来代替宏定义;
内联函数与宏的区别在于:宏是由预处理器来对宏进行替代,没有语法检查、类型检查和安全检查;内联函数是通过编译器的控制来实现的,有语法检查、类型检查和安全检查;内联函数是真正的函数,而且在调用的地方,由编译器负责把内联函数的函数体代码块替换到内联函数被调用的地方,这一点与宏替换很相似;内联函数有参数,有返回值;由于内联函数可以像宏一样被展开,所以调用内联函数的时候,取消了函数参数压栈、出栈所带来的开销,从而减少了函数调用开销;这就是内联函数的优越于宏的地方;
内联函数的声明和内联函数的函数体的定义必须在一起;下面声明内联函数的语句是无效的:
inline int Max(int a, int b);
而下面的内联函数的定义是有效的:
inline int Max(int a, int b){return ((a > b) ? a : b)};
C++类的成员函数也可以被定义为内联函数;比如:
class Student
{
private:
int nID
int nAge;
float fScore;
public:
void setID(int nid){ nID = nid; } //该成员函数默认自动为内联函数(隐式定义内联函数)
int getID(void){ return nID; } //该成员函数默认自动为内联函数(隐式定义内联函数)
inline void setAge(int nage) { nAge = nage; } //显式定义内联函数
inline int getAge(void) { return nAge; } //显式定义内联函数
void setScore(float fscore); //类定义体内没有声明为内联函数;
float getScore(void); //类定义体内没有声明为内联函数;
}
inline void Student::setScore(float fscore){ fScore = fscore; } //类定义体外实现为内联函数;
inline float Student::getScore(void) { return fScore; } //类定义体外实现为内联函数;
C++中,在类定义体内部定义了函数体的成员函数,被编译器默认为内联函数,而不管这个函数头前面是否有关键字inline,比如:setID()、getID()、setAge()、getAge();也可以把实现在类定义体外部的成员函数定义为内联函数,这个时候在类定义体中只有成员函数头的声明,而其实现是在类定义体外部,比如:setScore()和getScore();
即便是可以把实现在类定义体外部的成员函数定义为内联函数,那该成员函数的实现也必须写在声明类定义体的哪个头文件(.h)中,不能违反规则;即:内联函数的定义和实现都必须在同一个头(.h)文件中;
内联函数的局限性:
1、由于内联函数与宏一样也是实现为代码替换,所以定义为内联函数的函数体不宜过大,如果函数体过大,则某些普通的编译器就会放弃内联方式,而改用调用普通函数的方式,这样就失去了内联函数的意义了;所以,内联函数的函数体代码不宜过大,一般就是3---4行代码即可;
2、由于内联函数是编译器在便宜阶段进行函数体展开的,所以,这就把类的内联函数的定义与实现都必须在声明类的那个头文件中,而不能放在实现类的那个cpp文件中;这一点与模板template<>的特性相似;
引入内联函数的目的是为了解决程序中函数调用的效率问题。
函数是一种更高级的抽象。它的引入使得编程者只关心函数的功能和使用方法,而不必关心函数功能的具体实现;函数的引入可以减少程序的目标代码,实现程序代码和数据的共享。但是,函数调用也会带来降低效率的问题,因为调用函数实际上将程序执行顺序转移到函数所存放在内存中某个地址,将函数的程序内容执行完后,再返回到转去执行该函数前的地方。这种转移操作要求在转去前要保护现场并记忆执行的地址,转回后先要恢复现场,并按原来保存地址继续执行。因此,函数调用要有一定的时间和空间方面的开销,于是将影响其效率。特别是对于一些函数体代码不是很大,但又频繁地被调用的函数来讲,解决其效率问题更为重要。引入内联函数实际上就是为了解决这一问题。 在程序编译时,编译器将程序中出现的内联函数的调用表达式用内联函数的函数体来进行替换。显然,这种做法不会产生转去转回的问题,但是由于在编译时将函数休中的代码被替代到程序中,因此会增加目标程序代码量,进而增加空间开销,而在时间代销上不象函数调用时那么大,可见它是以目标代码的增加为代价来换取时间的节省。