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

C++ 中的 static 关键字:类成员、局部变量与单例模式

在前面我们聊过 C++ 的函数、引用、类与结构体。这次我们来看看一个常常让初学者迷惑的关键字:static

它的作用主要有三类:

  1. 类/结构体中的静态成员(全体实例共享)

  2. 局部静态变量(作用域局部,生命周期全局)

  3. 单例模式(利用静态变量确保唯一实例)


1. 类/结构体中的静态成员

先看一个例子:

#include <iostream>struct Entity
{int x, y;void Print() {std::cout << x << ", " << y << std::endl;}
};int main()
{Entity e;e.x = 2;e.y = 3;Entity e1 = {5, 8};e.Print();   // 2, 3e1.Print();  // 5, 8
}

这时 ee1 各自有独立的 xy


如果我们把它们改成静态的:

struct Entity
{static int x, y;
};

编译时会报错:

error LNK2001: 无法解析的外部符号 "public: static int Entity::x"

这是因为 静态成员变量需要在类外部进行定义,否则编译器不知道为它们分配存储空间:

int Entity::x;
int Entity::y;

这样就能正常使用了。

静态成员的特性

  • 静态成员变量在 所有实例中只有一份拷贝

  • 无论通过哪个对象修改它,所有对象看到的都是同一个值。

  • 使用时推荐直接写 Entity::x,而不是 e.x,因为它本质上不属于某个实例。

Entity e;
Entity::x = 2;
Entity::y = 3;Entity e1;
Entity::x = 5;
Entity::y = 8;std::cout << Entity::x << ", " << Entity::y;  // 输出 5, 8

这就像 Entity 类是一个“命名空间”,xy 属于它本身,而不是对象。


静态方法

静态方法也是类似的:

struct Entity
{static void Print() {std::cout << "Hello Entity" << std::endl;}
};

调用时不需要实例:

Entity::Print();

注意:静态方法不能访问非静态成员,因为它没有绑定到某个对象。


2. 局部 static 变量

static 不仅能用在类里,也能用在函数里:

void Function()
{static int i = 0;i++;std::cout << i << std::endl;
}

和普通局部变量的区别在于:

  • 普通局部变量:每次进入函数都会重新创建,退出函数就销毁。

  • 静态局部变量:只会在第一次调用函数时初始化一次,之后一直存在,直到程序结束。

运行:

for (int j = 0; j < 5; j++)Function();

输出:

1 2 3 4 5

这说明 i 在函数多次调用之间是共享的。

作用域与生命周期

  • 作用域:只在函数内可见。

  • 生命周期:整个程序。

这让它既能避免全局变量的污染,又能保持状态。


3. 单例模式(Singleton)

单例模式指的是 一个类在整个程序中只能有一个实例
在 C++ 中可以用 static 很方便地实现。

单例模式(Singleton)详解

为什么需要单例?

假设你要做一个游戏引擎,里面有个日志系统 Log
你希望:

  • 全局只有一个日志对象

  • 任何地方都能访问它

  • 不想每次用日志都要 new 一个对象

如果每次都写:

Log log1;
Log log2;

就可能有多个实例,日志配置不一致,管理起来很乱。
这时就希望**“某个类在全局只有一个实例”** —— 这就是单例模式。

单例模式的核心思想:


自己管住自己,不让别人随便创建对象,只暴露一个获取实例的方法。

  • 构造函数设为私有(private) → 别人不能随便 new

  • 类里放一个 static 实例 → 全局只有一份

  • 提供一个静态方法 Get() → 外部只能通过它来拿到这个实例

写法 1:类静态指针
#include <iostream>class Singleton
{
private:// 1. 构造函数私有化Singleton() {}// 2. 静态指针,存放唯一实例static Singleton* s_Instance;public:// 3. 静态方法,外部通过它获取实例static Singleton& Get(){if (s_Instance == nullptr)s_Instance = new Singleton(); // 第一次用时才创建return *s_Instance;}void Hello(){std::cout << "Hello from Singleton!" << std::endl;}
};// 类外初始化静态成员
Singleton* Singleton::s_Instance = nullptr;int main()
{// 获取唯一实例Singleton& s1 = Singleton::Get();Singleton& s2 = Singleton::Get();s1.Hello();s2.Hello();std::cout << &s1 << std::endl;std::cout << &s2 << std::endl; // 地址一样 → 确实只有一个对象
}

调用:

Singleton::Get().Hello();//运行结果
Hello from Singleton!
Hello from Singleton!
0x600003e00
0x600003e00

写法 2:局部静态变量(推荐)
class Singleton
{
public:static Singleton& Get(){static Singleton instance; // 第一次调用时创建,以后一直用这一个return instance;}void Hello(){std::cout << "Hello from Singleton!" << std::endl;}private:Singleton() {} // 构造函数私有化
};

调用:

Singleton::Get().Hello();//运行结果
Hello from Singleton!
Hello from Singleton!
0x600003e00
0x600003e00

特点:

  • 只会创建一次(第一次调用时)

  • 线程安全(C++11 起保证了 static 局部变量初始化是线程安全的)

  • 自动销毁(程序结束时,编译器会释放它)


http://www.dtcms.com/a/398829.html

相关文章:

  • 【 设计模式 | 行为型模式 观察者模式 】
  • seo 网站案例怀化优化网站排名
  • Rust 最小可行 MQ 架构实现指南
  • 公司网站设计报价电商网站建设设计报告总结
  • 【Python】迭代器
  • 【数据迁移】:MySQL 环境下【大表定义变更】一致性保障与数据迁移优化方案
  • 织梦禁止网站右击重庆企业
  • 金融系统的“防火墙”:数字孪生如何模拟风险攻击
  • 埃拉托斯特尼筛法(Sieve of Eratosthenes)——原理、复杂度与多种 C++ 实现
  • 【大模型-金融】Trading-R1 多阶段课程学习
  • 建网站知乎怎么样上传网站资料
  • jupyter notebook 使用集锦(持续更新)
  • 部署开源PPTagent 生成工具
  • Python的大杀器:Jupyter Notebook处理.ipynb文件
  • 物流网站建设与管理规划书七牛wordpress插件
  • 【同源策略】跨域问题解决方法(多种)
  • 【数据结构】链表 --- 单链表
  • ArcGIS JSAPI 高级教程 - 自由绘制线段、多边形
  • 【2025最新】ArcGIS 点聚合功能实现全教程(进阶版)
  • Express使用教程(二)
  • 大模型部署基础设施搭建 - Docker
  • 芜湖建设机械网站企业管理系统软件下载
  • 永嘉县住房和城乡规划建设局网站自助贸易网
  • 华为云学习笔记(1):ECS 实例操作与密钥登录实践
  • 有一次django开发实录
  • RISC-V 中的 Wait For Interrupt 指令 (wfi) 详解
  • 前端核心框架vue之(指令案例篇1/5)
  • 企业静态网站源码增城建设局网站
  • 网站兼容9公司logo和商标一样吗
  • 题解:AT_abc206_e [ABC206E] Divide Both