【C++】003、static关键字
一、static关键字的作用主要有两方面的作用改变生命周期和改变链接属性的作用域二、static关键字四个使用场景1、局部静态变量在函数内部本质变量的生命周期从栈变成全局静态存储区但作用域仍局限于函数内部特点局部静态变量只能被初始化一次之后函数调用结束该变量也不会被销毁下次调用该函数获取的还是上次的值线程安全从C11起局部静态变量的初始化是线程安全的。因为底层编译器会自动加锁这也是单例模式的底层实现原理代码实现void counter() { static int count 0; // 只初始化一次线程安全C11起 count; cout count endl; } // 调用3次输出1, 2, 32、全局静态变量/函数文件作用域本质全局静态变量和函数在当前文件中都可以调用而其他cpp文件无法调用该变量或函数。从外部链接变为内部链接。作用只在本编译单元.cpp文件中可见其他文件即使使用extern声明也无法访问。可用来隐藏实现细节防止多文件编译时的重名冲突比起全局静态C更推荐使用匿名的namespace来替换代码// FileA.cpp static int s_hidden 100; // 仅 FileA.cpp 可见 static void helper() {} // 仅 FileA.cpp 可见 // FileB.cpp extern int s_hidden; // ❌ 链接错误找不到该符号3、静态成员变量类内部本质属于类本身不属于某个对象所有该类的对象共享同一份内存在C17之前静态成员变量必须在类外单独定义并初始化否则会链接报错。因为一个头文件中的静态成员变量会被多个文件引用分不清到底是哪个类的静态变量。为解决上面问题在C17中引入 inline static允许在类内部进行初始化而无需去cpp文件中初始化代码class App { public: static int version; // 声明未定义 inline static int build 42; // C17起直接定义并初始化无需类外实现 }; // C17之前必须在 .cpp 文件补一行 // int App::version 1;4、静态成员函数类内部本质没有this指针无法访问普通成员变量与函数只能访问静态成员调用方式 通过类名::函数() 无需创建对象就可以调用静态成员函数静态成员函数不能是const静态函数与virtual虚函数。因为const函数修饰this指针而静态函数没有this。而virtual依赖于虚表vptr和对象静态函数不依赖对象代码class Math { public: static double square(double x) { return x * x; } }; double d Math::square(5.0); // 直接调用三、总结表格场景存储位置/生命周期作用域/链接性初始化次数局部变量静态存储区程序结束时才销毁函数内部/作用域为函数范围1次线程安全全局变量/函数静态存储区本文件内部内部链接1次程序启动时初始化静态成员函数静态存储区全局共享类域需外部定义1次静态成员函数无this属于类类域通过类名调用--四、static与thread_local变量区别static变量所有线程共享一份thread_local修饰的变量每个线程独享一份