当前位置: 首页 > article >正文

c++ static(详解)

C++中,static关键字用于定义具有静态存储持续时间的变量或方法。它在不同上下文中有不同的含义,通常与变量的存储方式和作用域相关。static的主要作用是控制变量或函数的可见性和生命周期。

可以通过一个生活中的场景来形象化static的作用:

场景:

假设你是一位图书馆管理员,负责管理图书馆中每个人的借书记录。每次有新成员登记时,你都为他们创建一个新的借书账户,并记录他们借的书。但图书馆有一个总借书数的统计,也就是说,不管有多少个会员借书,所有人的借书数量都会加在一起,形成一个全馆的总借书数。

静态变量的作用:

  • 借书账户的个人记录:每个会员都有自己借书的记录(类似于类的普通成员变量),每个人只能看到自己借了几本书。
  • 图书馆的总借书数:图书馆有一个总借书数的统计,这个数字对所有会员来说是共享的(类似于static成员变量),每个会员借了一本书后,这个总数都会增加。

对应到C++代码:

#include <iostream>

using namespace std;

class LibraryMember{
public:
    int personalBorrowedBooks = 0; //个人借书记录

    static int totalBorrowedBooks; //总借书数(所有人共享)

    void borrowBook(){
        personalBorrowedBooks++; //总借书数增加
        totalBorrowedBooks++; //总借书数增加
    }
    void showBorrowInfo(){
        cout <<"You have borrowed " << personalBorrowedBooks << " books." << endl;
        cout <<"The liberary has loand out " << totalBorrowedBooks << " book in total." << endl;
    }

};

//初始化静态成员变量
int LibraryMember::totalBorrowedBooks = 0;

int main(){

    LibraryMember member1;
    LibraryMember member2;

    member1.borrowBook();  // member1借了1本书
    member2.borrowBook();  // member2借了1本书
    member1.borrowBook();  // member1又借了1本书

    cout << "memeber1 Info " << endl;
    member1.showBorrowInfo() ;  // 显示member1的信息
    cout << "memeber2 Info " << endl;
    member2.showBorrowInfo();  // 显示member2的信息

    return 0;
}

输出结果:

memeber1 Info 
You have borrowed 2 books.
The liberary has loand out 3 book in total.
memeber2 Info 
You have borrowed 1 books.
The liberary has loand out 3 book in total.

分析:

  1. 个人借书记录(非静态成员变量):每个LibraryMember对象有自己独立的借书记录。member1借了2本书,而member2借了1本书,他们各自的记录是独立的。
  2. 总借书数(静态成员变量):所有成员共享一个总借书数,不管是哪个成员借了书,这个总借书数都会增加。

静态的现实意义:

static 就像图书馆的总借书统计,它不会因为某个会员的加入或离开而被重新设置或注销,始终保持一个全局的、共享的状态。这类似于生活中我们对一些全局、共享数据的统计与追踪,所有人都可以贡献,但数据是统一维护的。

1. 静态成员变量

静态成员变量(类的静态变量)属于整个类,而不是某个具体的对象。它们在所有对象中共享,也就是说,不管创建了多少个类对象,静态成员变量在内存中只有一份,且对所有对象都是共用的。

  • 作用:用于存储类的全局状态,所有对象共享该状态。
class MyClass {
public:
    static int staticVar;
    MyClass() { staticVar++; }  // 每次创建对象时都会递增
};

int MyClass::staticVar = 0;  // 静态变量需要在类外初始化

int main() {
    MyClass obj1;
    MyClass obj2;
    cout << MyClass::staticVar;  // 输出 2
}

2. 静态成员函数

静态成员函数和静态成员变量类似,它们属于整个类,而不是某个对象。静态成员函数只能访问静态成员变量,不能访问非静态成员变量,因为非静态成员变量依赖于具体的对象实例。

  • 作用:用于不依赖对象的功能实现,比如操作静态成员变量。
class MyClass {
public:
    static int staticVar;
    static void printStaticVar() {
        cout << staticVar << endl;  // 可以访问静态变量
    }
};

int MyClass::staticVar = 0;

int main() {
    MyClass::printStaticVar();  // 直接通过类名调用静态函数
}

3. 静态局部变量

在函数内部,static 局部变量的生命周期贯穿整个程序的执行,而不仅仅是在函数调用期间。它在函数第一次被调用时初始化,并在程序的整个生命周期内保持其值。

  • 作用:用于需要在函数多次调用时保持其状态的场景。
void countCalls() {
    static int count = 0;  // 只初始化一次
    count++;
    cout << "This function has been called " << count << " times" << endl;
}

int main() {
    countCalls();  // 输出 1
    countCalls();  // 输出 2
    countCalls();  // 输出 3
}

4. 静态全局变量

static 修饰的全局变量(在函数或类外定义)只能在定义它的文件中访问,无法被其他文件访问。这是一种用于控制链接的方式,通常用于实现模块间的数据隔离,防止名称冲突。

  • 作用:用于在一个源文件中定义只对该文件可见的变量。
static int fileVar = 0;  // 只能在当前文件中使用

5. 静态函数(文件作用域)

类似于静态全局变量,static 修饰的函数只能在定义它的文件中使用。这在大型项目中非常有用,因为它可以防止不同文件中的函数名冲突。

  • 作用:用于限制函数的可见性,使其仅在定义的文件中可用。
static void helperFunction() {
    // 只能在当前文件中调用
}

6. 使用场景总结

  • 共享类成员:静态成员变量和静态成员函数在类的不同实例之间共享数据。
  • 维护函数状态:静态局部变量用于在函数调用之间保持状态。
  • 文件级作用域:静态全局变量和静态函数用于实现文件内的变量和函数封装,避免命名冲突。
  • 效率提升:静态成员函数可以在不创建对象的情况下直接调用,减少对象的开销。

static 在C++中用于控制变量或函数的生命周期作用域,在代码优化、模块化设计等方面发挥着重要作用。


http://www.kler.cn/a/311097.html

相关文章:

  • 如何从头开始构建神经网络?(附教程)
  • XSS安全基础
  • uniapp 设置安全区域
  • mysql5.7安装SSL报错解决(2),总结
  • 【css】html里面的图片宽度设为百分比,高度要与宽度一样
  • Springboot整合Prometheus+grafana实现系统监控
  • Snowflake怎么用?
  • 系统架构设计师 云原生架构篇
  • 字符设备驱动 — 4 异常与中断
  • 【Elasticsearch系列七】索引 crud
  • 【Java】网络编程-地址管理-IP协议后序-NAT机制-以太网MAC机制
  • 爬虫逆向学习(六):补环境过某数四代
  • C++初阶学习第六弹------标准库中的string类
  • 每日刷题(算法)
  • 开发一个电商API接口的步骤!!!
  • microchip中使用printf给AVR单片机串口重定向
  • Redis实现发布/订阅功能(实战篇)
  • uniapp中实现<text>文本内容点击可复制或拨打电话
  • tronado websocket
  • Java基础:Api 文档注释,字符串种类,String字符串创建,特点及常用方法
  • 【洛谷】P1546 [USACO3.1] 最短网络 Agri-Net 的题解
  • SqlServer自定义类型的使用
  • 【数据结构-一维差分】力扣1893. 检查是否区域内所有整数都被覆盖
  • 无人机滑环的核心特点及其应用分析
  • [论文笔记] LLM端侧小模型篇——1、剪枝量化的latency
  • MySQl篇(基本介绍)(持续更新迭代)