1、 作用域(Scope)
作用域(scope)是指一个标识符(比如变量名、函数名等)在程序中有效的一个区域。定义在函数内部的变量称为局部变量(Local Variable),它的作用域仅限于函数内部, 离开该函数后就是无效的,再使用就会报错。
1)局部作用域(Local Scope)
在函数或代码块内定义的变量只能在该函数或代码块内部访问。一旦函数或代码块执行完毕,该变量即被销毁。
例如,
#include <iostream> using namespace std; int fn(int a){ int b,c; //a,b,c仅在函数fn()内有效 return a+b+c; } int main(){ int m,n; //m,n仅在函数main()内有效 return 0; }
2)全局作用域(Global Scope)
在所有函数外部定义的变量称为全局变量(Global Variable),它的作用域默认是整个程序,也就是所有的源文件,包括 .cpp
和 .h
文件。在所有函数之外定义的变量在整个文件中都可访问。这种变量会在程序启动时分配内存,并在程序结束时释放。
例如,
#include <iostream> using namespace std; int a, b=3; //全局变量 void fn(){ cout << a << endl << b << endl; } int main(){ fn(); cout << a << endl << b << endl; return 0; }
3)类作用域(Class Scope)
类的成员变量和成员函数在类作用域内可见,类的成员可以通过对象或指针访问。
#include <iostream> using namespace std; class MyClass { public: int member; // 类作用域内的成员变量 void method() { // 类作用域内的成员函数 cout << "Method is called. Member value is: " << member << endl; } }; int main() { MyClass obj; // 实例化对象 obj.member = 10; // 访问并设置成员变量 obj.method(); // 调用成员函数 return 0; }
4)文件作用域(File Scope)
静态变量和函数在文件作用域内可见。文件作用域的变量和函数只能在定义它们的文件中访问。
// file_scope_example.cpp #include <iostream> using namespace std; static int fileScopedVariable = 42; // 文件作用域变量 static void fileScopedFunction() { // 文件作用域函数 cout << "File scoped function. Variable value: " << fileScopedVariable << endl; } int main() { fileScopedFunction(); // 调用文件作用域函数 return 0; }
5)语句作用域(Statement Scope)
语句作用域(Statement Scope)指的是在特定语句块 { }
中定义的变量,其作用域仅限于该块内部。如 for
循环中的变量定义,只在该语句块内有效。
#include <iostream> using namespace std; int main() { int x = 10; // 在 main 函数作用域内定义变量 x cout << "x in main scope: " << x << endl; { // 进入新的语句作用域 // 在此作用域中定义一个新的 x, // 覆盖 main 中的 x int x = 20; cout << "x in inner scope: " << x << endl; } // 语句块结束,此作用域的 x 超出作用域被销毁 // 输出 main 函数作用域的 x cout << "x back in main scope: " << x << endl; // 循环内的 i 仅在 for 语句作用域内有效 for (int i = 0; i < 3; ++i) { cout << "i in for loop scope: " << i << endl; } // cout << i; // 这里访问 i 会出错, //因为 i 超出了 for 循环的作用域 return 0; }
2、局部变量与全局变量的区别
1)局部变量是声明在块或者函数内部的变量。局部变量的作用域局限于该块或者函数。局部变量如果没有初始化,将包含垃圾数据。
2)全局变量是在所有块和函数之前声明的变量。全局变量对所有在它之后声明的函数有效。全局变量有默认值初始化,如0
。
注意:如果要调用另外一个文件中的全局变量,如果再声明一个同名的全局变量,那么编译器会因为重名报错,这个时候就要使用extern
变量。extern
声明告诉编译器这个变量的定义在其他文件中,所以并不会为它分配内存。
#include <iostream> using namespace std; int globalVar = 100; // 全局变量 void myFunction() { int localVar = 10; // 局部变量 globalVar += 10; // 可以访问并修改全局变量 cout << "Inside myFunction - localVar: " << localVar << ", globalVar: " << globalVar << endl; } int main() { // main 函数内的局部变量, // 与 myFunction 中的 localVar 不同 int localVar = 5; cout << "Inside main - localVar: " << localVar << ", globalVar: " << globalVar << endl; myFunction(); // 调用 myFunction 函数 cout << "After calling myFunction - localVar: " << localVar << ", globalVar: " << globalVar << endl; return 0; }
3、静态局部变量和静态全局变量区别
1)非静态全局变量的作用域是整个源程序 ,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。
2)静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效,在同一源程序的其它源文件中不能使用它。
3)示例代码
#include <iostream> using namespace std; // 静态全局变量,作用域仅限于当前文件 static int globalCounter = 0; // 非静态全局变量,可以被其他文件访问(如果有外部链接) int nonStaticGlobalCounter = 0; void staticLocalExample() { // 静态局部变量,作用域仅限于此函数内,但生命周期贯穿程序始终 static int localCounter = 0; localCounter++; cout << "Static Local Counter: " << localCounter << endl; } void staticGlobalExample() { globalCounter++; cout << "Static Global Counter: " << globalCounter << endl; } int main() { cout << "Calling staticLocalExample() multiple times:" << endl; staticLocalExample(); // 第一次调用,localCounter = 1 staticLocalExample(); // 第二次调用,localCounter = 2 staticLocalExample(); // 第三次调用,localCounter = 3 cout << "\nCalling staticGlobalExample() multiple times:" << endl; staticGlobalExample(); // 第一次调用,globalCounter = 1 staticGlobalExample(); // 第二次调用,globalCounter = 2 staticGlobalExample(); // 第三次调用,globalCounter = 3 return 0; }
4、C++命名空间(Namespace)
命名空间用于组织代码,以防止名称冲突。C++允许通过命名空间将函数、类和变量分组。常用的命名空间是 std,其中包含C++标准库的所有内容。
1)命名空间的定义
访问命名空间中作用域内实体
命名空间名::命名空间成员名;
标准命名空间std
C++标准库所有标识符都是在一个名为std的命名空间中定义的,或者说标准头文件中函数、类和对象模板是在命名空间std
中定义的。可以在文件开头加入 using namespace std;
使用时就可以不写std::
。
使用示例:
#include <iostream> using namespace std; namespace Animal { void Show() { //如果上面没using namespace std; 则使用cout需要std::cout cout << "Animal" << endl; } } namespace Person { void Show() { //如果上面没using namespace std; 则使用cout需要std::cout cout << "Person" << endl; } } int main() { Animal::Show(); Person::Show(); return 0; }
2)使用命名空间
完全限定名称:在使用命名空间中的变量或函数时,使用 命名空间名称::元素名称
的方式。
MyNamespace::myFunction();
使用 using
指令:使用 using namespace
指令可以将整个命名空间的内容引入当前作用域。
using namespace MyNamespace;
myFunction(); // 可以直接调用,不需要加前缀
使用 using
声明:只将命名空间中的特定元素引入当前作用域。
using MyNamespace::myFunction;
myFunction(); // 可以直接调用
3)匿名命名空间
匿名命名空间是没有名称的命名空间,其内容仅在定义它的文件中可见。这是一种创建文件作用域的有效方式。
#include <iostream> namespace { // 匿名命名空间内的变量和函数 int hiddenVar = 42; void hiddenFunction() { std::cout << "This is a function inside an anonymous namespace." << std::endl; } } void testFunction() { // 可以在当前编译单元中访问匿名命名空间内的内容 std::cout << "Value of hiddenVar: " << hiddenVar << std::endl; hiddenFunction(); } int main() { testFunction(); // 无法从外部直接访问匿名命名空间内的内容 // std::cout << hiddenVar; // 错误:不能直接访问匿名命名空间中的 hiddenVar // 错误:不能直接调用匿名命名空间中的 // hiddenFunction(); hiddenFunction return 0; }
4)嵌套命名空间
C++17 引入了嵌套命名空间的简化语法,使得定义嵌套命名空间更简洁。
#include <iostream> namespace OuterNamespace { namespace InnerNamespace { void display() { std::cout << "Inside InnerNamespace!" << std::endl; } } } // 使用 C++17 的简化嵌套命名空间语法 namespace OuterNamespace::NestedNamespace { void show() { std::cout << "Inside NestedNamespace!" << std::endl; } } int main() { // 调用 InnerNamespace 中的函数 OuterNamespace::InnerNamespace::display(); // 调用 NestedNamespace 中的函数 OuterNamespace::NestedNamespace::show(); return 0; }