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

相关推荐
王旭·wangxu_a43 分钟前
【例43.3】 转二进制
c语言·数据结构·c++·python·算法·蓝桥杯-算法提高·基础问题
醒了不起的盖茨比Z1 小时前
动态主机配置协议 (DHCPv4)介绍,详细DHCP协议学习笔记
c语言·网络·c++·嵌入式硬件·网络协议·计算机网络·网络安全
I"ll carry you3 小时前
【C++基础】enum,union,uint8_t,static
java·数据库·c++
Zfox_3 小时前
【Linux】应用层自定义协议与序列化
linux·服务器·c语言·c++
*TQK*3 小时前
C++/C语言判断重复数组(zznu)⭐
c语言·数据结构·c++
可涵不会debug5 小时前
Git在码云上的使用指南:从安装到推送远程仓库
linux·运维·服务器·c++·git
Flocx5 小时前
联合体(Union)
开发语言·网络·c++·stm32
迂幵myself5 小时前
14-1C++STL的初始
开发语言·c++