【static关键字】在C++中的不同场景应用


前言

本文记录C++中static关键字在不同场景下的使用方式和作用。 关于static关键字的用法,不仅是研发面试环节中常被问到的一个重要知识点,在实际的项目研发过程中更是一个能经常见到的关键字,作为研发工程师有必要熟练掌握! https://www.cnblogs.com/happyamyhope/p/10429434.html https://blog.csdn.net/ypshowm/article/details/89030194

一、修饰变量

1. 修饰全局变量

全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。

这两者的区别在于非静态全局变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其它源文件中被使用而引起错误,这也就是因为 static全局变量只初使化一次,从而防止在其他文件单元中被引用。

2. 修饰局部变量

修饰局部变量时,表明该变量的值不会因为函数终止而丢失。

静态局部变量和一般的局部变量有以下不同之处:
(1)该变量在全局数据区分配内存(同部变量在栈区分配内存);
(2)静态局部变量在程序执行到交对象的声明处时被首次初始化,即以后的函数调用不再进行初始化(局部变量每次函数调用都会被初始化);
(3)静态局部变量一般在声明处初始化,如果没有显式初始化,会被程序自动初始化为0(局部变量不会被初始化);
(4)它始终驻留在全局数据区,直到程序运行结束。但其作用域为局部作用域,也就是虽然它还存在,但不能在函数体外面使用它(局部变呈在栈区,在函数结束后立即释放内存);

3.修饰类中的成员变量

当用static关键字修饰类中的成员变量时,这样的成员变量就称为静态成员变量。

注意:
(1)静态成员变量实际上就是类域中的全局变量,必须初始化,且只能在类体外,初始化时不受private和protected访问限制。
(2)静态成员变量属于类,不属于某个具体的对象。因此即使创建多个对象,也只为静态成员变量分配一份内存,所有对象使用的是这份内存中的数据,当某个对象修改了静态成员变量,也会影响到其他的对象。static成员变量不占用对象内存,在所有对象外开辟内存,不创建对象也可以访问。
(3)static成员变量和普通static变量一样,编译时在静态数据区分配内存,到程序结束时才释放。这就意味着static成员变量不随对象的创建而分配内存,也不随对象的销毁而释放内存。而普通成员变量在对象创建时分配内存,在对象销毁时释放内存。
(4)static成员变量初始化不赋值会被默认初始化,一般是 0。静态数据区的变量都有默认的初始值,而动态数据区(堆区、栈区)的变量默认是垃圾值。
(5)静态成员变量的类型可以是所属类的类型,但是普通成员变量不行。普通成员只能声明为所属类类型的指针或引用。

ps
不能在定义对象时对变量初始化,就是不能用构造函数来初始化,而应该在类外初始化。这是因为类中的静态变量是属于类的,不属于某个对象!而且使用时::前加的应该是类名,而不是对象。代码示例见二-1。

二、修饰函数

1. 修饰类中的函数

如果这个静态函数出现在类里,那么它被称为静态成员函数。
静态成员函数的作用在于:调用这个函数不会访问或者修改任何对象(非static)数据成员。这是因为类的静态成员(变量和方法)属于类本身,在类加载的时候就会分配内存,可以通过类名直接去访问;非静态成员(变量和方法)属于类的对象,所以只有在类的对象产生(创建类的实例)时才会分配内存,然后通过类的对象(实例)去访问。

在使用的时候最直观的区别:静态成员函数可以直接在外部调用,而非静态成员函数则要先实例化出对象然后才能调用。

注意:
(1)静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数;
(2)非静态成员函数可以任意地访问静态成员函数和静态数据成员;
(3)静态成员函数不能访问非静态成员函数和非静态数据成员;
(4)调用静态成员函数,可以用成员访问操作符(.)和(->)为一个类的对象或指向类对象的指针调用静态成员函数,也可以用类名::函数名调用(因为他本来就是属于类的,用类名调用很正常)

StaticTest.h

class StaticTest
{
public:
    int a;
    static int b;
    StaticTest();
    void NormalFunc();
    static void StaticFunc();
};

StaticTest.cpp

#include <iostream>
#include "StaticTest.h"

using namespace std;

int StaticTest::b = 2;  // 静态变量在类外初始化!

StaticTest::StaticTest()
{
    a = 1;
}

void StaticTest::NormalFunc()
{
    cout << "This is a normal function" << endl;

    cout << a << endl;
    cout << b << endl;

    StaticTest::StaticFunc();

    cout << endl;
}

void StaticTest::StaticFunc()
{
    cout << "This is a static function" << endl;

    // cout << a << endl;  // 报错,静态函数不能访问非静态成员变量
    cout << b << endl;

    StaticTest::NormalFunc();  // 报错,静态函数不能访问非静态成员函数

    cout << endl;
}

main.cpp

#include <iostream>
#include "StaticTest.h"

using namespace std;

int main()
{
    // cout << StaticTest::a << endl;  // 报错,对于类中的普通变量需要生成对象才能调用
    StaticTest object;
    cout << object.a << endl;  // 这才对
    cout << StaticTest::b << endl;  // 正确,因为静态变量属于类

    return 0;
}

2. 修饰不在类中的函数

对于不出现在类中的函数而言,加了static关键字的静态函数就是一个普通的静态全局函数,只能在本cpp文件中调用,不能被其它cpp文件调用,而不加static关键字的函数是可以在其它cpp文件中被调用的。

OutFunction.cpp

#include <iostream>

using namespace std;

void NormalFunc()
{
	cout << "NormalFunc" << endl;
}

static void StaticFunc()
{
	cout << "StaticFunc" << endl;
}

main.cpp

#include <iostream>

using namespace std;

void NormalFunc();
static void StaticFunc();

int main()
{
    NormalFunc();  // 成功调用
    StaticFunc();  // 报错
    return 0;
}

总结

本博客分情况介绍了C++种static关键字再不同场景下的具体应用,希望大家都有所收获!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值