【C++研发面试笔记】1. C++常见关键字含义
1.1 inline
定义内联函数,该关键字是基于定义的。如果只在函数声明时给出inline,则函数不会被认为是内联函数,所以必须在函数定义的地方也加上inline。其主要特性:
一个函数若声明inline,则每处声明都必须保证是inline,类成员函数若在类定义内给出定义,则隐含inline。 声明定义内联函数时,编译器将所调用的代码嵌入到主调函数中。编译器在必要或更符合预期的目标代码质量,其也有权不实际内联。
1.2 const
定义常量成员,包括const数据成员和const成员函数,const数据成员必须也只能通过构造函数的初始化列表进行初始化。
const成员函数只能访问类的成员,不能进行修改,如果需要修改,则引入下面的mutable关键字。
1、const修饰普通变量(两种写法都类似)
const TYPE value;
TYPE const value;
2、const修饰指针
指针本身是常量不可变:(char*) const pContent;
指针所指向的内容是常量不可变:const (char) *pContent;或(char) const *pContent;
两者都不可变:const char* const pContent;
3、const修饰函数
const修饰函数参数是它最广泛的一种用途,它表示在函数体中不能修改参数的值(包括参数本身的值或者参数其中包含的值)
4、const修饰类对象/对象指针/对象引用
const修饰类对象表示该对象为常量对象,其中的任何成员都不能被修改。对于对象指针和对象引用也是一样。const修饰的对象,该对象的任何非const成员函数都不能被调用,因为任何非const成员函数会有修改成员变量的企图。
5、const修饰数据成员
const数据成员只在某个对象生存期内是常量,而对于整个类而言却是可变的。因为类可以创建多个对象,不同的对象其const数据成员的值可以不同。所以不能在类声明中初始化const数据成员,因为类的对象未被创建时,编译器不知道const 数据成员的值是什么。
6、const修饰成员函数
const修饰类的成员函数,用const修饰的成员函数不能改变对象的成员变量。一般把const写在成员函数的最后。
7、const常量与define宏定义的区别
A. 编译器处理方式不同:define宏是在预处理阶段展开;const常量是编译运行阶段使用。 B. 类型和安全检查不同:define宏没有类型,不做任何类型检查,仅仅是展开;const常量有具体的类型,在编译阶段会执行类型检查。 C. 存储方式不同:define宏仅仅是展开,有多少地方使用,就展开多少次,不会分配内存;const常量会在内存中分配(可以是堆中也可以是栈中)。
8、使用单独的变量初始化const引用
使用单独的变量初始化const引用的值不会产生额外的存储空间,通过修改原先的变量是可以修改常量引用的值的。
1.3 mutable
mutable也是为了突破const的限制而设置的。
被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中。
这个关键字的引入是解决const成员函数要修改成员变量,通常而言,const成员函数只能访问成员变量,不能修改成员,但是如果成员变量被mutable修饰了,则在const成员函数中可以修改该变量。
mutable和const不能同时用于修饰成员变量。
1.4 static
声明静态成员,包括静态数据成员和静态成员函数,它们被类的所有对象共享,静态数据成员在使用前必须初始化,而静态成员函数只能访问静态数据成员,不能访问非静态数据成员,因为该函数不含有this指针。
1. 面向过程的static关键字
(1)静态全局变量:
全局变量前,加上关键字static,该变量就被定义成为一个静态全局变量。
1、该变量在全局数据区分配内存; 2、未经初始化的静态全局变量会被程序自动初始化为0; 3、静态全局变量在声明它的整个文件都是可见的,而在文件之外是不可见的。其它文件中可以定义相同名字的变量,不会发生冲突。定义全局变量就可以实现变量在文件中的共享。
TIPS:一般程序的由new产生的动态数据存放在堆区,函数内部的自动变量存放在栈区。自动变量一般会随着函数的退出而释放空间,静态数据(即使是函数内部的静态局部变量)也存放在全局数据区。全局数据区的数据并不会因为函数的退出而释放空间。
(2)静态局部变量:
在局部变量前,加上关键字static,该变量就被定义成为一个静态局部变量。
静态局部变量保存在全局数据区,而不是保存在栈中,每次的值保持到下一次函数调用,直到下次赋新值。
静态局部变量有以下特点:
1、该变量在全局数据区分配内存; 2、静态局部变量在程序执行到该对象的声明处时被首次初始化,即以后的函数调用不再进行初始化; 3、静态局部变量一般在声明处初始化,如果没有显式初始化,程序自动初始化为0; 4、它始终驻留在全局数据区,直到程序运行结束。但其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束。
(3)静态函数:
在函数的返回类型前加上static关键字,函数即被定义为静态函数。静态函数与普通函数不同,它只能在声明它的文件当中可见,不能被其它文件使用。其它文件中可以定义相同名字的函数,不会发生冲突。
2. 面向对象的static关键字
(1)静态数据成员
在类内数据成员的声明前加上关键字static,该数据成员就是类内的静态数据成员。
对于非静态数据成员,每个类对象都有自己的拷贝。而静态数据成员被当作是类的成员。无论这个类的对象被定义了多少个,静态数据成员在程序中也只有一份拷贝,由该类型的所有对象共享访问。
1、对该类的多个对象来说,静态数据成员只分配一次内存,供所有对象共用。 2、静态数据成员存储在全局数据区。静态数据成员定义时要分配空间,所以不能在类声明中定义。 3、静态数据成员和普通数据成员一样遵从public,protected,private访问规则。 4、静态数据成员在全局数据区分配内存,属于本类的所有对象共享,所以,它不属于特定的类对象。 5、在没有产生类对象时其作用域就可见,即在没有产生类的实例时,我们就可以操作它; 6、静态数据成员初始化与一般数据成员初始化不同。静态数据成员初始化的格式为: <数据类型><类名>::<静态数据成员名>=<值> 7、类的静态数据成员有两种访问形式: <类对象名>.<静态数据成员名> 或 <类类型名>::<静态数据成员名> 8、静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其它全局名字冲突的可能性。
(2)静态成员函数
与静态数据成员一样,我们也可以创建一个静态成员函数,它为类的全部服务而不是为某一个类的具体对象服务。静态成员函数与静态数据成员一样,都是类的内部实现,属于类定义的一部分。
普通的成员函数一般都隐含了一个this指针,this指针指向类的对象本身,因为普通成员函数总是具体的属于某个类的具体对象的。通常情况下,this是缺省的。但是与普通函数相比,静态成员函数由于不是与任何的对象相联系,因此它不具有this指针。从这个意义上讲,它无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数,它只能调