目录
一、内联函数:
内联函数的由来:
如果一些函数被频繁调用,就会不断地有函数入栈,造成栈空间或栈内存的大量消耗。在系统下,栈空间是有限的,假如频繁大量的使用就会造成因栈空间不足所造成的程式出错的问题为了解决这个问题,就引入了inline修饰符,表示为内联函数。
inline int Add(int& a, int& b)// inline + 函数定义
{
int tmp = a;
a = b;
b = tmp;
}
内联函数的使用:
在最开始,为了解决因代码量少且又会被频繁调用的函数造成栈空间或栈内存的大量消耗这个问题,一般会选择用宏来替代函数的功能。但为什么在C++中就引入inline关键字去替代宏呢?
内联函数相比于宏的优势:
1、宏是预处理指令,在预处理阶段的时候把所有的宏名用宏体来替换,所以宏是不方便调试的;内联函数是函数,在编译阶段把所有调用内联函数的地方把内联函数插入,方便调试;
2、宏没有类型安全的检查,内联函数在编译时会进行对应的类型检查。
3、在进行编写时,内联函数的限制比宏要小。
4、宏无法操作类的私有数据成员。
使用内联函数的注意事项:
1、关键字inline 必须与函数定义体放在一起才能使函数成为内联,仅将inline 放在函数声明前面不构成内联函数。
// inline仅与函数声明放在一起
inline void Test1(int a);
void Test1(int a)// 不构成内联函数
{
//...
}
// 与函数定义体放在一起
void Test2(int a);
inline void Test2(int a)// 构成内联函数
{
//...
}
这也说明了inline 是一种“用于实现的关键字”,而不是一种“用于声明的关键字”。
2、inline的使用是有所限制的,只适合代码简单的函数使用,不能包含复杂的结构控制语句例如while、switch等,且内联函数本身不支持自己调用自己(递归)。
3、C++中在类中定义的所有函数都自动称为内联函数,类的成员函数的定义直接写在类的声明中时,不需要inline关键字(隐式内联)。
谨慎使用内联函数:
既然内联能提高函数的执行效率,为什么不把所有的函数都定义成内联函数?
内联是以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。如果执行函数体内代码的时间,相比于函数调用的开销较大,那么效率的收获会很少。另一方面,每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。内联在本质上就是一种空间换时间的做法。
不宜使用内联函数的场景:
1、代码量大的场景:如果函数体内的代码比较长,使用内联将导致内存消耗代价较高。
2、代码结构复杂的场景:如果函数体内出现循环等复杂的结构控制语句,那么执行函数体内代码的时间要比函数调用的开销大。
二、类和对象:
类的定义:
C++为了实现面向对象的编程,引入了类的概念:class。
class有些类似于结构体。
class内部(类体)的内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者成员函数。
class ClassName // ClassName为定义的类的名字
{
private: //私有成员,缺省存取权限
// 数据成员及成员函数
int a1;
void Test1(); // 若函数声明与定义不分离,编译器可能会将其当成内联函数进行处理
public: //公有成员
// 数据成员及成员函数
int a2;
void Test2();
protected: //保护成员
// 数据成员及成员函数
int a3;
void Test3();
};
注明:
private、public、protected 都为访问限定符。
私有成员(private):只允许类内成员函数访问
公有成员(public):允许类内和类外函数访问
保护成员(protected):允许类内和其派生类函数访问
class的默认访问权限为private,struct为public
类对象大小计算:
类对象中只存储成员变量,不存储成员函数,因为一个类实例化出N个对象,每个对象的成员变量都可以存储不同的值,但是调用的函数却是同一个。如果每个对象都存储成员函数,但这些成员函数却是一样的,就会造成大量空间的浪费。
计算规则与结构体的计算规则相同,但是要注意没有成员变量的类大小是1,而不是0。因为要1表示它存在。
三、this指针:
C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有成员变量的操作,都是通过该指针去访问。
class Test
{
public:
int _a;
int _b;
Test(int a = 10, int b = 20) // this指针指向构造函数传参时传入的对象,也就是A。
{ // this本质上是“成员函数”的形参
this->_a = a;
this->_b = b;
}
};
int main()
{
Test A(1, 2);// 传参初始化
}
this指针的特性:
1、this指针的类型:类类型* const,即成员函数中,不能给this指针赋值。
2、this指针只能在“成员函数”的内部使用
3、this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给 this形参。所以对象中不存储this指针。
4、this指针是一个形参,存放于栈中,有些特殊的编译器会存放于寄存器中。