C++系列之static关键字

static关键字有什么作用?

这也算是面经中老生常谈的问题了,看来不懂的同学没有好好的刷面经啊。

那么本文就来好好解释一下这个问题。

C++的static关键字主要的功能有:改变作用域改变变量在内存模型中的存储位置。修饰不同的变量会有不同的效果,现在我们来一一说明。

先放总结:

(1)static修饰全局变量,该变量作用域由global变成当前文件

(2)static修饰全局函数,该函数作用域由global变成当前文件

(3)static修饰函数局部变量,该变量生命周期从原本贯穿函数调用期间,变成贯穿整个程序,但其作用域依然局限在所在函数作用域。

(4)static修饰类的成员变量或成员函数,称为静态成员,静态成员被类的所有对象共有。静态成员具有以下特性:

  • 静态成员被类的所有对象所共有
  • this指针无法指向静态成员
  • 静态函数无法更改或调用非静态成员
  • 静态成员可以直接用类调用,如:Family::static_var,Family::static_func()

为了方便,代码验证使用Visual Studio 2019,建议读者也把下面代码手敲运行一遍。

修饰全局变量

当一个变量被定义成全局变量时,该变量的作用域为global,全局变量可以跨文件使用。当用static修饰成员变量时,该变量的作用域仅在当前文件。

未用static进行修饰

测试代码如下:

c++ 复制代码
// file.cpp
int cs = 1;

// another_file.cpp
#include <iostream>

extern int cs;
int main() {
    std::cout << "全局变量cs=" << cs << std::endl;
    return 0;
}

测试实况:

输出结果:

使用static修饰全局变量

测试代码如下:

c++ 复制代码
// file.cpp
static int cs = 1;

// another_file.cpp
extern int cs;
int main() {
    std::cout << "全局变量cs=" << cs << std::endl;
    return 0;
}

测试实况:

输出结果:

IDE提示链接错误,这就是因为变量cs的作用域仅限file.cpp,在another_file.cpp无法访问到cs

结论

static关键字修饰全局变量时会使其作用域从全局变成当前文件范围。

修饰全局函数

static修饰全局函数时,效果和全局变量一样,也是将其作用域从全局变成了当前文件范围。

未使用static修饰

测试代码:

c++ 复制代码
// file.cpp
int add(int a, int b) {
    return a + b;
}

// another_file.cpp
#include <iostream>

extern int add(int a, int b);
int main() {
    std::cout << add(2, 3) << std::endl;
    return 0;
}

测试实况:

测试结果:

在another_file.cpp可以正常调用file.cpp中的全局函数。

使用static修饰全局函数

测试代码:

c++ 复制代码
// file.cpp
static int add(int a, int b) {
    return a + b;
}

// another_file.cpp
#include <iostream>

extern int add(int a, int b);

int main() {
    std::cout << add(2, 3) << std::endl;
    return 0;
}

测试实况:

测试结果:

链接失败。

结论

同全局变量一样,用static修饰全局函数后,该函数的作用域从全局变成当前文件。

修饰函数中的局部变量

用static修饰函数的局部变量时,延长局部变量的生命周期,使其贯穿整个程序。

c++ 复制代码
// test_func.cpp

#include <iostream>

void func() {
    int a = 1;
    static int b = 1;
    std::cout << "a=" << a++ << ", b=" << b++ << std::endl;   
}

int main() {
    for (int i = 0;i < 5; i++) {
        func();
    }

    return 0;
}

测试结果:

局部变量a,在每次函数调用都会被重新赋值,生命周期仅限于函数调用期间。

而被static修饰的局部变量b在每次函数调用后都会持续增加,函数调用结束后也不会被销毁,生命周期持续到程序结束。

结论

static修饰函数局部变量时,会延长该局部变量的生命周期,直到程序结束。

这是因为未被修饰的局部存在栈中,函数调用结束后,该栈空间会被回收,连带成员变量一起回收。

而被static的函数成员变量存在内存模型中的"常量区",该区域的变量会直到程序结束才会被销毁。

修饰类成员

被static类的成员变量或成员函数称为静态成员,该静态成员会归属于类,被所有该类实例化的对象共享。举个例子,静态成员就像家里的空调,是所有家庭成员共享的,所有家庭成员都能使用,且不独属于某个家庭成员。

但是静态成员有几个特点

(1)不能在静态成员函数修改非静态成员变量或者调用非静态成员函数

(2)静态成员可以直接用类访问:Family::air

(3)this指针无法指向静态成员:this->air 会报错

测试代码:

c++ 复制代码
#include <iostream>
#include <string>

class Family {
public:
    static int air; // 静态成员变量声明
    std::string role;

    Family(std::string role) : role(role) {}

    static void static_printAir() {
        std::cout << "全家一起用空调,当前 air=" << air << std::endl;
    }

    void printAir() {
        std::cout << this->role <<"使用空调," << "当前 air=" << air << std::endl;
    }
};

// 静态成员变量定义(必须在类外)
int Family::air = 20;

int main() {
    Family husband("丈夫");
    Family wife("妻子");

    Family::air++;
    Family::static_printAir(); // 输出: 当前 air=21

    husband.air++; // 修改静态成员变量
    husband.printAir(); // 输出: 当前 air=22

    wife.air++; // 再次修改静态成员变量
    wife.printAir(); // 输出: 当前 air=23

    husband.static_printAir(); // 类实例对象也可以调用静态成员函数

    return 0;
}

测试结果:

结论

静态成员被类的所有成员共同拥有

this指针无法指向静态成员

相关推荐
逆小舟1 小时前
【Linux】人事档案——用户及组管理
linux·c++
风中的微尘6 小时前
39.网络流入门
开发语言·网络·c++·算法
混分巨兽龙某某7 小时前
基于Qt Creator的Serial Port串口调试助手项目(代码开源)
c++·qt creator·串口助手·serial port
小冯记录编程7 小时前
C++指针陷阱:高效背后的致命危险
开发语言·c++·visual studio
C_Liu_7 小时前
C++:类和对象(下)
开发语言·c++
coderxiaohan8 小时前
【C++】类和对象1
java·开发语言·c++
阿昭L8 小时前
MFC仿真
c++·mfc
老赵的博客10 小时前
c++ unqiue指针
java·jvm·c++
程序猿编码11 小时前
基于 Linux 内核模块的字符设备 FIFO 驱动设计与实现解析(C/C++代码实现)
linux·c语言·c++·内核模块·fifo·字符设备
怎么没有名字注册了啊11 小时前
MFC_Install_Create
c++·mfc