关于C++中static关键字的总结

本文目录

  • 一、用在局部作用域
  • 二、用在全局作用域
  • 三、用在类作用域
    • 1. 静态数据成员
    • 2. 静态函数成员
  • 四、static变量的存放位置

因为最近要保研和找实习,所以重新复习了一下C++的知识,static的用法很丰富,就想整理一下。

一、用在局部作用域

首先回顾一下作用域的概念:

作用域是指一个标识符在程序正文中有效的区域。对于函数体内的变量,作用域从声明处起到所在块结束的大括号为止,对于函数的形参,从声明处起到函数体结束为止。

在局部作用域中,如果一个对象声明为static,即在对象的声明前加上“static”关键字,则该对象具有静态生存期,这个对象不会随着多次函数调用而产生一个副本,也不会因为函数的返回而失效。
由于函数返回之后,在函数外部实际上无法访问static的对象,所以static的函数用法多出现在递归的函数中。

int factorial(int n){
     
    static int result=1;
    if(n==0){
     
        return result;
    }else{
     
        return n * factorial(n-1);
    }
}

比如上面的函数,result变量为static,在多次调用中只会初始化第一次,这里初始化为1。需要注意的是,动态基本类型变量未初始化会被赋予随机值,静态基本类型变量则默认初值为0。

二、用在全局作用域

在全局作用域中的变量,在整个文件中都有效。但是不加static的变量和函数,则默认是extern变量,在该模块以外的所有模块中都是可见的。这带来的问题是,不同人开发的模块很可能出现变量重名,当多文件工程很大需要引用多个模块时更是如此,所以我们需要隐藏一些不必要外部可见的变量。
static正是提供了这一功能。被static修饰的变量或函数,无法被其他编译单元引用。

在ISO C++ 2.0标准中不再鼓励这种用法,如果想要隐藏该模块的变量和函数不为外部可见,鼓励使用匿名命名空间的方式。由于每个源文件的匿名空间是不同的,所以在一个源文件中没有办法访问其他源文件的匿名命名空间。

以下为一个多文件项目:
a.cpp

#ifndef UNTITLED_A_H
#define UNTITLED_A_H
void func1();
static void func2();
#endif //UNTITLED_A_H

a.cpp

#include 
#include "a.h"
using namespace std;
void func1(){
     
    cout << "func1" << endl;
}
static void func2(){
     
    cout << "func2" << endl;
}

main.cpp

#include 
#include "a.h"
using namespace std;
int main() {
     
    func1();
    func2();
    return 0;
}

这里func1()是外部可见的,func2()是外部不可见的,因此会提示如下错误:
warning: 'void func2()' used but never defined

三、用在类作用域

这里分为静态数据成员和静态函数成员。

1. 静态数据成员

如果一个类中的数据成员用static修饰,该成员不属于任何一个对象独有,而是整个类所共有。该变量将具有静态生存期,而且可以不通过对象,而是通过类的方式“类名::标识符”直接访问。

2. 静态函数成员

同理,如果一个函数用static修饰,则该函数为整个类所共有的函数,可以直接通过“类名::函数名(参数)”来调用。当然通过对象名调用也是可以的,等价于通过类名来调用。

下面举个例子来说明两种静态成员。

#include 
using namespace std;
class A{
     
public:
    A(){
     
        cout << "constructor"<<endl;
        count ++;
    }
    A(A &a){
     
        cout << "copy constructor"<<endl;
        count ++;
    }
    static int getcount(){
     
        return count;
    }
private:
    static int count;
};
int A::count = 0;
int main() {
     
    cout << A::getcount()<<endl;
    A a;
    A b = a;
    cout << A::getcount()<<endl;
    return 0;
}

这里count为static变量,这里注意c++的类静态数据成员变量必须在类外初始化,即使该变量为private类型。getcount是一个类的静态函数成员,可以不依赖类的对象调用。
在主函数中,还没有一个对象存在时,getcount函数就可以返回count值,此时为初始化的0。当声明了两个对象之后,getcount的值将会变成2。
运行结果:

0
constructor
copy constructor
2

四、static变量的存放位置

对于c++来讲,编译运行程序占用内存大体分为数据段和代码段,数据段又可分为:全局存储区,堆区,栈区,常量存储区。
函数存放在代码段中,static修饰的变量和全局变量都放在全局存储区中。全局存储区又可分为初始化的数据段(.data)和未初始化的数据段(.bss)。如果static变量可以在程序运行前确定初值,将放入.data中,如果不能,比如static变量是通过执行构造函数赋予初值,则无法在运行前确定初值,则放入未初始化的数据段.bss中。

你可能感兴趣的:(c++,编程语言)