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指针无法指向静态成员

相关推荐
深思慎考3 小时前
微服务即时通讯系统(服务端)——用户子服务实现逻辑全解析(4)
linux·c++·微服务·云原生·架构·通讯系统·大学生项目
草莓火锅5 小时前
用c++使输入的数字各个位上数字反转得到一个新数
开发语言·c++·算法
j_xxx404_5 小时前
C++ STL:阅读list源码|list类模拟|优化构造|优化const迭代器|优化迭代器模板|附源码
开发语言·c++
散峰而望5 小时前
C/C++输入输出初级(一) (算法竞赛)
c语言·开发语言·c++·算法·github
曾几何时`6 小时前
C++——this指针
开发语言·c++
小冯的编程学习之路6 小时前
【C++】: C++基于微服务的即时通讯系统(1)
开发语言·c++·微服务
淀粉肠kk8 小时前
【C++】map和set的使用
c++
纵有疾風起8 小时前
C++—vector:vecor使用及模拟实现
开发语言·c++·经验分享·开源·stl·vector
爱凤的小光12 小时前
图漾GM461-E1相机专栏
c++
qwepoilkjasd12 小时前
C++智能指针介绍
c++