mmxingye

导航

07 | C++中的static和inline

非类的成员函数以及成员变量

  • inline修饰的函数或变量(c++17开始可以修饰变量)在全局保留一份

  • static修饰的函数或者变量会在各自的编译单元都保留一份

  • static函数的局部static变量也会有多份,inline函数的static变量只有一份;

  • static inline 修饰的函数或者变量与static单独修饰的效果一致;

  • inline 不能修饰局部变量;

有关类的成员函数以及成员变量

  • 类的非const静态成员变量初始化,C++ 17可以通过static inline 在类内直接初始化,C++17之前必须在类外初始化(const static 修饰的变量也可以类内初始化,这个在之前也是可以的);

  • C++17之后,类的静态成员变量在类内通过static声明,在类外(但是在头文件中)初始化不加inline的话可能会导致重定义从而出现链接错误,而加了inline 就不会出错,类似有无inline修饰的全局函数;

  • C++ 17之前必须在.cpp中初始化静态成员才不会出现重定义的错误,在.h中初始化还是会导致重定义错误,因为C++17之前的标准不支持inline修饰类的静态成员变量;

  • 类中的函数其实可以认为是都隐式加了inline的,因为类中的所有函数在全局都只有一份,而有无static修饰只是限制该函数对类数据成员的使用(类的static函数只能使用static成员变量,类的普通成员函数可以使用所有的成员变量 );

C++ 17之前为什么类的非const静态成员必须类外初始化?

  • 因为类的静态成员是类所有,不属于任何对象,如果放在类内初始化,那么每个对象构造的时候都会对该静态成员进行初始化,这样会导致其他对象在使用该静态成员时出现意想不到的错误,所以禁止类内初始化非const静态变量;
  • 而const修饰的静态成员变量是在类中初始化,对象构造的时候不会再进行初始化操作,对象构造的时候默认该变量已经初始化了,反正也不能修改它;
  • C++17之前的类内静态变量必须在类外初始化,如果有头文件和实现文件,最好在类的实现文件中对静态变量做初始化,如果在头文件中做初始化,也会引起重定义的问题;
  • C++17 之后可以在类内通过static inline 直接进行声明与初始化,也可以在类内部进行声明,在类外(但是在头文件中)通过inline 进行初始化。其实就是新标准通过inline能够保证类内静态变量只初始化一次,全局共享一份数据,而之前的标准是不允许inline修饰类的静态成员变量的;

举个现实中的小例子

第一阶段

main.cpp

#include "test.h"
#include "test2.h"

int main() {

}

test.h

bool a = true;

test2.h

#include "test.h"

我们看一下编译结果

编译期出现的问题

严重性 代码 说明 项目 文件 行 禁止显示状态
错误 C2374 “a”: 重定义;多次初始化

第二阶段

我们将 test.h修改如下

#pragma  once
bool a = true;

我们接着编译一下

链接期出现的问题

严重性 代码 说明 项目 文件 行 禁止显示状态
错误 LNK2005 "bool a" (?a@@3_NA) 已经在 test.obj 中定义

第三阶段

我们将 test.h修改如下

#pragma  once
inline bool a = true;

生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个

相信大家看到这里就明白 inline 变量的一个使用场景了!

当然你也可以将其定义放到.cpp文件中,同样可以避免第二阶段链接期的错误!

posted on 2022-04-27 21:06  独立树  阅读(2971)  评论(0编辑  收藏  举报