static在C/C++中的作用详解

本文详细介绍了static在C/C++中的作用以及使用方法,本文分两部分:
第一部分介绍static在c语言中的作用;
第二部分介绍static在c++中的作用;

Source.cpp文件内代码

/*Source.cpp file*/
#include "Header.h"

static int a = 1;
int b = 1;	//声明,也是定义

static int add1(int a, int b) {			/*①*/
	return a + b;
}

int addsum(int i) {
	static int a = 0;		/*②*/
	//int a = 0; //每次调用函数a将被重新赋值
	return a += i;
}

int add(int a, int b) {
	return add1(a, b);
}

void myprint(void) {
	static int m[2];		/*③*/
	int n[2];				/*④*/
	printf("%s_%s(%03d):m=%d\n", __FILE__, __func__, __LINE__, *m);
	printf("%s_%s(%03d):n=%d\n", __FILE__, __func__, __LINE__, *n);
	return;
}

说明:
①被static修饰的函数作用域为本文件,全局区分配内存,在main.cpp文件调用该函数将会在编译阶段出错
②被static修饰的局部变量在全局数据区分配内存;其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束,但是该变量的声明周期没有结束,如在main.cpp函数中循环调用的打印结果:变量初始化一次,但是函数运行结束其值一直被保存。
③被static修饰的变量没有被初始化时,默认初始化为0值。
④未被static修饰的变量没有初始化时,其默认值未知!!

Header.h文件内容

#ifndef  __HEADER_H_
#define  __HEADER_H_

#include <stdio.h>

static int add1(int a, int b);
int addsum(int i);
int add(int a, int b);
void myprint(void);

#endif // ! __HEADER_H_

main.cpp文件内容

#include "Header.h"
#include <stdio.h>

int main(int argc, char *argv[]) {
	//printf("line:%d, 计算两个数相加和,3+5=%d", __LINE__, add1(3, 5)); //error
	printf("line:%d, 计算两个数相加和,3+5=%d\n", __LINE__, add(3, 5));
	//extern int a;
	extern int b;	// //声明,不是定义
	for (int i = 0; i <= 10; ++i) {
		//printf("line:%d, 函数返回值为:%d\n", __LINE__, addsum(a)); // error		/*①*/
		printf("line:%d, 函数返回值为:%d\n", __LINE__, addsum(b));					/*②*/
	}
	myprint();
	getchar();
	return 0;
}

说明:
①使用的是extern int a 由于在Source.cpp文件中a被static修饰,故编译阶段报错
②extern int a为外部变量,其值为1
在这里插入图片描述
总结:
全局变量在外部使用声明时,extern关键字是必须的,如果变量没有extern修饰且没有显式的初始化,同样成为变量的定义,因此此时必须加extern,而编译器在此标记存储空间在执行时加载内并初始化为0。而局部变量的声明不能有extern的修饰,且局部变量在运行时才在堆栈部分分配内存。

—————————————————————————————————————————————

static 在C++中的使用

本段代码演示static修饰累的成员函数以及类的成员变量
本段代码还演示了使用static修饰构造函数创建一个单例模式的对象

Header.h文件

#ifndef __HEADER_H_
#define __HEADER_H_

#include <iostream>
#include <windows.h>
#include <winnt.h>

using namespace std;
class Singleton {
public:
	/*使用静态成员函数获取单例对象*/
	static Singleton *GetInstance() {
		return m_Instance;
	}
	static int GetTest() {
		return Singleton::val_Test;
	}
	static int AddTest() {
		return Singleton::val_Test += 100;
	}
private:
	//无参构造函数
	Singleton() { m_Test = 10; }			
	//有参构造函数
	Singleton(int data = 10):m_Test(data) { }	
	/*使用静态成员变量维护唯一对象*/
	static Singleton *m_Instance;
	static int val_Test;
	int m_Test;

	// This is important
	class GC {
	public:
		~GC() {
			// destory all the resouce here, eg:db connector, file handle and so on
			if (m_Instance != NULL) {
				std::cout << "Here is the test!" << std::endl;
				delete m_Instance;
				m_Instance = NULL;
			}
		}
	};
	static GC gc;	//定义一个私有静态类对象,类主要功能是在程序结束时回收资源
};

class testtest
{
public:
	testtest() { a = 10; }
	int a;
	static int i;			// 此处只是声明变量
	static int add();		// 声明
};

#endif // ! __HEADER_H_

Source.cpp文件

#include "Header.h"

Singleton *Singleton::m_Instance = new Singleton(1);
Singleton::GC Singleton::gc;
int Singleton::val_Test = 10;

int testtest::i = 1000;		// 此处是定义,少了此处会链接错误
int testtest::add()			// 定义
{
	//访问类的静态成员变量只能通过作用域限定符访问,由于静态成员函数没有this指针,所以不能使用
	//this->a方式访问类的成员变量
	std::cout << testtest::i + 1 << std::endl;
	//std::cout << a << std::endl;		//error
	return testtest::i += 1;
}

main.cpp主函数

#include "Header.h"

int main(int argc, char *argv[]) {

	testtest a;
	testtest b;
	std::cout << "&a.add()=0x" << (a.add) << std::endl;
	std::cout << "&b.add()=0x" << (b.add) << std::endl;
	testtest::add();
	std::cout << "&a.a=0x" << &(a.a) << std::endl;
	std::cout << "&b.a=0x" << &(b.a) << std::endl;

	
	Singleton  *singletonObj1 = Singleton::GetInstance();
	singletonObj1->AddTest();
	std::cout << singletonObj1->GetTest() << std::endl;
	std::cout << "singletonObj1的地址:0x" << singletonObj1 << std::endl;

	Singleton  *singletonObj2 = Singleton::GetInstance();
	std::cout << singletonObj2->GetTest() << std::endl;
	std::cout << "singletonObj2的地址:0x" << singletonObj1 << std::endl;

	Singleton  *singletonObj3 = Singleton::GetInstance();
	std::cout << singletonObj3->GetTest() << std::endl;
	std::cout << "singletonObj3的地址:0x" << singletonObj1 << std::endl;

	getchar();
	return 0;
}

在这里插入图片描述
总结:
① 类的静态成员函数域静态成员变量属于整个类,而不属于某个对象,因此通过两个不同对象获取add()函数地址相同。
② 非静态成员变量以及成员函数属于每个对象,属于对象独有所以内存地址不同。
③ 类对象指针singletonObj1、singletonObj2、singletonObj3指向同一块内存。
—————————————————————————————————————————————
(由于工作经验和水平有限,此文仅做抛砖引玉,如有错误敬请指出)
本人建立了一个C/C++学习讨论群,感兴趣的同学可以申请加入:
加入该群的连接为:
https://blog.csdn.net/qq_35118533/article/details/105306618

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值