C++: 作用域与生命周期

最后更新:2026-08-26

变量不是"定义在哪里都能用"。

有些变量只能在某对大括号里用,有些变量能在所有函数里用,还有些变量在函数结束后还能"记住"上次的值。

这就是作用域生命周期


1. 作用域(Scope)

作用域就是变量能被访问的范围。

(1) 1.1 三种作用域

作用域类型 声明位置 能被访问的范围
局部作用域 函数内部 从声明处到函数结束
全局作用域 所有函数外部 从声明处到文件结束(其他文件也能用 extern 访问)
块作用域 语句块内部(如 iffor 从声明处到块结束

▶ 示例 1:局部变量 vs 全局变量(难度⭐)

CPP
#include <iostream>

int gGlobalVar = 100; // 全局变量

void foo() {
 int localVar = 5; // 局部变量
 std::cout << "foo: localVar = " << localVar << std::endl;
 std::cout << "foo: gGlobalVar = " << gGlobalVar << std::endl;
}

int main() {
 foo();
 // std::cout << localVar << std::endl; // ❌ 错误:localVar 在 foo 里声明,main 里看不到
 std::cout << "main: gGlobalVar = " << gGlobalVar << std::endl; // ✅ 全局变量在哪都能用
 return 0;
}
▶ 试一试

输出:

TEXT 📖 仅展示
foo: localVar = 5
foo: gGlobalVar = 100
main: gGlobalVar = 100

💡 重点: 局部变量和全局变量同名时,局部变量优先(就近原则)。

CPP
#include <iostream>

int x = 100; // 全局变量

int main() {
 int x = 5; // 局部变量(与全局变量同名)
 std::cout << "x = " << x << std::endl; // 输出 5(局部变量优先)
 std::cout << "::x = " << ::x << std::endl; // 输出 100(用 :: 访问全局变量)
 return 0;
}


2. 块作用域

ifforwhile 等语句块里声明的变量,只能在块里用。

CPP
#include <iostream>

int main() {
 if (true) {
 int blockVar = 5; // 块作用域
 std::cout << "块里:blockVar = " << blockVar << std::endl;
 }
 // std::cout << blockVar << std::endl; // ❌ 错误:blockVar 在块外不存在
 return 0;
}

💡 提示: for 循环的循环变量(如 int i = 0)也有块作用域,但 C++11 之后推荐把循环变量声明在 for 里面,这样它的作用域就限制在循环里。



3. 生命周期(Lifetime)

生命周期就是变量从"诞生"到"消亡"的时长。

存储类别 生命周期 作用域 关键字
自动变量 函数调用时诞生,函数结束时消亡 局部 (默认)
静态局部变量 程序启动时诞生,程序结束时消亡 局部 static
全局变量 程序启动时诞生,程序结束时消亡 全局 (默认)
静态全局变量 程序启动时诞生,程序结束时消亡 文件内 static

(1) 3.1 自动变量(默认)

CPP
#include <iostream>

void foo() {
 int x = 5; // 自动变量(默认)
 std::cout << "x = " << x << std::endl;
 x++; // 修改 x
 std::cout << "x = " << x << std::endl;
}

int main() {
 foo(); // 输出:x = 5, x = 6
 foo(); // 输出:x = 5, x = 6(x 重新创建了)
 return 0;
}

💡 重点: 自动变量在函数调用时创建,函数结束时销毁。下次再调用函数,变量是重新创建的(值不会保留)。

(2) 3.2 静态局部变量(static

CPP
#include <iostream>

void foo() {
 static int x = 5; // 静态局部变量(只初始化一次)
 std::cout << "x = " << x << std::endl;
 x++; // 修改 x
}

int main() {
 foo(); // 输出:x = 5
 foo(); // 输出:x = 6(x 保留了上次的值)
 foo(); // 输出:x = 7
 return 0;
}

💡 重点: static 局部变量只初始化一次,而且函数结束后不会销毁,下次调用函数时,它的值会保留。



4. 全局变量

(1) 4.1 基本用法

CPP
#include <iostream>

int gCount = 0; // 全局变量

void increment() {
 gCount++; // 修改全局变量
}

int main() {
 std::cout << "初始值:gCount = " << gCount << std::endl;
 increment();
 increment();
 std::cout << "调用两次后:gCount = " << gCount << std::endl;
 return 0;
}

(2) 4.2 全局变量的优缺点

优点 缺点
所有函数都能访问 破坏封装性(任何函数都能修改)
不用传参数 让程序难以理解(不知道谁改了它)
多线程时需要加锁(后面会学)

💡 建议: 尽量避免用全局变量!如果多个函数需要共享数据,用参数传递。



5. 静态全局变量

(1) 5.1 基本用法

CPP
// file1.cpp
static int sFileVar = 5; // 静态全局变量(只能在 file1.cpp 里用)

// file2.cpp
extern int sFileVar; // ❌ 错误:file2.cpp 看不到 sFileVar

💡 重点: static 全局变量只能在当前文件里用,其他文件无法通过 extern 访问。这能避免命名冲突。



6. 实战:计数器函数

▶ 示例 2:用静态局部变量实现计数器(难度⭐⭐)

CPP
#include <iostream>

int getCount() {
 static int count = 0; // 静态局部变量
 count++;
 return count;
}

int main() {
 std::cout << "第 " << getCount() << " 次调用" << std::endl;
 std::cout << "第 " << getCount() << " 次调用" << std::endl;
 std::cout << "第 " << getCount() << " 次调用" << std::endl;
 return 0;
}
▶ 试一试

输出:

TEXT 📖 仅展示
第 1 次调用
第 2 次调用
第 3 次调用

💡 提示: 这个技巧常用在"工厂函数"、"单例模式"等场景(后面会学)。



7. 常见错误

(1) 7.1 在作用域外访问变量

错误示例:

CPP
#include <iostream>

int main() {
 if (true) {
 int x = 5;
 }
 std::cout << x << std::endl; // ❌ 错误:x 在 if 块外不存在
 return 0;
}

编译错误信息:

TEXT 📖 仅展示
error: 'x' was not declared in this scope

(2) 7.2 忘记写 static

错误示例:

CPP
#include <iostream>

void foo() {
 int x = 0; // ❌ 忘记写 static
 x++;
 std::cout << "x = " << x << std::endl;
}

int main() {
 foo(); // 输出:x = 1
 foo(); // 输出:x = 1(期望是 2)
 return 0;
}

▶ 示例 3:局部变量 vs 块作用域变量(难度⭐)

CPP
#include <iostream>

int globalX = 100; // 全局变量

int main() {
    int x = 10; // main 函数的局部变量

    {
        int x = 20; // 块作用域变量,遮蔽外层的 x
        std::cout << "块内 x = " << x << std::endl;
        std::cout << "全局 x = " << globalX << std::endl;
    }

    std::cout << "块外 x = " << x << std::endl;

    return 0;
}
▶ 试一试

输出:

TEXT 📖 仅展示
块内 x = 20
全局 x = 100
块外 x = 10

❓ 常见问题

Q 全局变量和静态全局变量有什么区别?
A > - 全局变量:所有文件都能访问(用 extern) > - 静态全局变量:只能在当前文件里访问
Q 为什么我的程序里全局变量的值莫名其妙变了?
A 可能是其他函数修改了它。
Q 局部变量和全局变量同名时,怎么访问全局变量?
A:: 作用域解析运算符。 > > int x = 100; // 全局变量 > > int main() { > int x = 5; // 局部变量 > std::cout << "局部 x = " << x << std::endl; // 5 > std::cout << "全局 x = " << ::x << std::endl; // 100 > return 0; > } >

📖 小节


📝 作业

  1. 基础题 (Difficulty ⭐): 写一个程序,包含:

  2. 一个全局变量 gTotal

  3. 一个函数 void addToTotal(int x),给 gTotal 加上 x

  4. main 里调用 addToTotal 三次,然后输出 gTotal

  5. 进阶题 (Difficulty ⭐⭐): 写一个函数 int getUniqueId(),每次调用返回一个唯一的 ID(从 1 开始,每次加 1)。

  6. 用静态局部变量实现

  7. main 里调用五次,输出结果

  8. 挑战题 (Difficulty ⭐⭐⭐): 写一个程序,包含以下函数:

  9. void push(int x):把 x 加入全局数组

  10. int pop():从全局数组取出最后一个元素

  11. void printStack():打印全局数组的所有元素

静态全局变量限制数组只能在当前文件里用(把数组声明为 static)。


8. 🚀 下一步

学会了作用域和生命周期,接下来我们学习 数组与字符串(第15课)—— 处理多个同类型的数据,以及 C++ 的字符串。

Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏