本文详细介绍了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