C++:Static

1 在内存中所在的位置

回想C++程序中内存的划分是什么呢?从上到下首先是内核空间,然后是栈内存,内存映射段,堆,数据段,和代码段。用一张图的解释就是:

在这里主要探讨static,因此主要讨论数据段。数据段用于存储静态全局变量、静态局部变量和静态常量等静态数据,在程序运行期间,数据段的大小固定不变,但其内容可以被修改。按照变量是否被初始化,数据段可分为已初始化数据段和未初始化数据段。

2 不在类中的static

2.1 全局静态变量:

在所有函数外部定义的变量称之为全局变量,作用域默认是整个程序,也就是所有的源文件包括.cpp和.h文件。而当static修饰全局变量时候,变量的存储区域在全局数据区的静态常量区。变量的作用域由整个程序变为当前文件。文件作用域的声明在缺省的情况下为external链接属性,如定义全局变量 in a = 1,a的链接属性为external,而加上static会修改变量的缺省链接属性,为internal。internal不能为其他文件所访问。因此得出结论,static修饰的全局变量即全局静态变量只能作用于当前文件中。

2.2 局部静态变量

定义在函数内部的变量成为局部变量,非局部静态变量的作用域仅限于函数内部,离开该函数后就是无效的。当static修饰局部变量时,变量的存储区域由栈变为静态常量区。变量的生命周期由局部调用结束变为程序运行结束。

函数调用开辟栈帧,函数中的局部变量在栈上分配存储空间,当函数执行完毕,函数栈帧销毁,栈空间由系统回收。而在static修饰函数局部变量的时候,其修饰的局部变量只执行初始化一次,延长了局部变量的生命周期,直到程序运行结束以后才释放,但不改变作用域。

2.3 静态函数

普通的函数作用域与全局变量一样都是整个程序。

当static修饰函数的时候,函数的作用域由整个程序变成当前文件。

3 在类中的static

3.1 类的静态成员

在类内成员变量的声明前加上关键字static,则该数据成员就是类内的静态数据成员。静态成员可以在多个对象之间进行数据共享,因为静态数据保存在数据段中,因此静态成员变量一共就一份,无论这个类被定义了多少次,静态成员变量都只分配一次内存。是由改类的所有对象共享访问的。(数据段中的变量都有默认的初始值,堆区栈区的变量默认值都是垃圾值。)

所有类都共享,是因为单独的在数据段中开辟的内存,因此不占用对象的内存。如下代码,类A的大小和类B的大小是一样的,虽然类A中多定义了一个static。

#include<iostream>
using namespace std;

class A
{
public:
	int a1;
	static int a2;
};
class B
{
public:
	int b1;
};
int main()
{
	
	A a;
	B b;
	cout << sizeof(a) << endl;
	cout << sizeof(b) << endl;
	return 0;
}

result:
4
4

因为static变量开辟在别的区,因此在没有类的实例的时候,静态成员变量就已经存在了,就可以操作他。因此,就可以不用声明对象,直接对类中的静态成员变量进行赋值,如下代码,最终结果可以直接输出,很神奇。

#include<iostream>
using namespace std;

class A
{
public:
	int a1 = 0;
	static int a2;
};
class B
{
public:
	int b1;
};
int A::a2 = 2;
int main()
{
	
	cout << A::a2;
	return 0;
}

上述代码中,其实还有一个大坑,不知道看到了没,就是关于静态成员变量的初始化。int A::a2这一行,这个是静态的初始化方式,是在加载时完成的初始化,即在main函数执行前由运行时调用响应的代码进行初始化的。还有一种方法叫动态初始化,代码如下,记住,静态成员必须初始化必须初始化必须初始化,并且只能在类外只能在类外只能在类外,就是 int A::a2这个。

int A::a2;
int main()
{
	A::a2 = 2;
	cout << A::a2;
	return 0;
}

3.2 类的静态成员函数

声明为static的类成员函数成为类的静态成员函数。静态成员函数没有this指针,因为类的静态成员函数是属于整个类而非类的对象,所以没有this指针,这就导致了只能访问类的静态数据和静态成员函数。并且不能将静态成员函数定义为虚函数。

注意,静态成员函数只能访问静态变量,不能访问非静态变量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值