基础语法
About 5 min
基础语法
关键字
inline
作用: 使用inline修饰的函数称为内联函数,编译器会尝试对该函数进行内联优化,在保证函数特性的同时,避免函数调用开销,提高了程序执行效率。
原理: 函数的频繁调用存在开销(栈操作、参数传递、返回值传递、指令指针保存与恢复、上下文切换等),内联就是编译器用已编译好的二进制代码替换对该函数的调用指令。内联类似于宏函数,但是宏函数仅是文本的替换,而内联函数是在编译中完成的,不是在预处理完成的,优于宏函数.
注意事项:
- 内联增加程序的内存占用和缓存未命中的概率,进而影响程序性能。
- 频繁调用的简单函数适合内联,稀少调用的复杂函数不适合内联。
- 递归函数和虚函数不能内联,递归函数的跳出是由运行时上一层的结果决定的,编译时无法获知。
- inline关键字仅表示期望该函数进行内联优化,但是否适合内联则完全由编译器决定。有些函数没有加inline也会被编译器处理内联优化,而有些函数(如递归函数)即便加了inline也会被编译器忽略。
const
修饰基本类型:
作用: 当const修饰基本类型时,该基本类型的值在初始化之后就不能被改变。同时,在声明该基本类型时就必须设定初始值。
const int a = 10;
// a = 20; // 编译时报错,常量的值不可修改
// const int b; // 编译时报错,常量在声明时必须设定处置
修饰对象:
作用: 被const关键字修饰的对象、对象指针或对象引用,统称为常对象(不可变对象)。常对象只能调用常函数,不能调用非常函数;非常对象既可以调用常函数,也可以调用非常函数。
class MyClass {
public:
void modify() { /* 修改对象状态 */ }
void display() const { /* 不修改对象状态 */ }
};
const MyClass obj;
obj.display(); // 常对象 可以调用const成员函数
// obj.modify(); // 编译时报错,常对象不可以调用
修饰成员函数:
作用: 当const修饰成员函数时,这表示该成员函数不会修改它所属对象的任何成员变量(除非这些成员变量被声明为mutable)。这样的成员函数可以被const对象调用。
mutable
作用: 在被const修饰的成员函数中修改一个成员变量的值,需要将这个成员变量修饰为mutable。即用mutable修饰的成员变量不受const成员方法的限制。
class MyClass {
public:
void func() const {
a = 4;
}
mutable int a;
};
volatile
作用: volatile关键字用于告知编译器某个变量的值可能会在程序的其他部分被改变,编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。
使用场景:
- 防止编译器优化:编译器通常会对代码进行优化,例如将变量的值缓存到寄存器中以提高执行效率。但某些变量(如硬件寄存器或共享变量)的值可能会被程序外部的事件或线程改变,此时不应当读取寄存器中的缓存数据。
- 硬件访问:当程序直接与硬件进行交互时(如操作寄存器),这些寄存器的值可能会被硬件在任何时候改变。为了保证从寄存器中读取到的值是最新的,应该将这些寄存器声明为volatile。
- 多线程编程:在多线程程序中,一个线程可能会修改另一个线程正在访问的变量。为了确保所有线程看到的变量值是最新的,应该将这些共享变量声明为volatile。注意:volatile并不保证原子性、不提供锁机制,在多线程环境中如需确保线程安全及操作的顺序,需要使用其他同步机制。
static
修饰成员变量: 使用static修饰一个类中的成员变量,可以使其成为被局限在类中使用的全局资源,可以把静态成员变量理解为被限制在类中使用的全局变量。
- 静态成员变量需要在类的外部单独定义和初始化。
class MyClass{
public:
MyClass(int data = 0):m_data(data){}
int m_data;
static int s_data; // 声明
};
int MyClass::s_data = 20; // 定义和初始化
- 对象中只包含普通成员变量,不包含静态成员变量。
MyClass a(10);
std::cout << "size= " << sizeof(a); // 结果为4。
- 静态成员变量也要受到类的访问控制限定符(public、private等)的约束。
- 在类的外部访问静态成员变量,可以使用 类名::静态成员变量 或使用 对象.静态成员变量 进行访问。
MyClass a(10);
std::cout << MyClass::s_data;
std::cout << a.s_data; // 对象实例中虽然不包含静态成员变量,但是可以进行使用。
修饰成员函数: 被 static 修饰的成员函数即为静态成员函数。
- 静态成员函数和普通的成员函数一样,既可以直接定义在类的内部,也可以定义在类的外部。
- 静态成员函数没有this指针,没有const属性,可以将其理解为被限制在类中使用的全局函数。
- 静态成员函数和静态成员变量一样,也要受到类的访问控制限定符的约束。
- 静态成员函数中只能访问静态成员;非静态成员函数中既可以访问静态成员,也可以访问非静态成员。
- 在类的外部访问静态成员函数,可以使用 类名::静态成员函数(实参表) 或 对象.静态成员函数(实参表)。
class MyClass{
public:
MyClass(int data = 0):m_data(data){}
int m_data;
static int s_data; // 声明
};
int MyClass::s_data = 20; // 定义和初始化