C++之static,静态变量

目录

1.为什么要用静态变量

2.全局变量

3.静态局部变量

4.静态数据成员的空间开辟

5.静态数据成员

6.释放

7.总结

1.内存:

2.初始化:

3.最大的优点:

4.指针:

5.释放时机:


1.为什么要用静态变量

前面我们定义学生类统计学生信息,只统计了学生的学号、姓名、性别,如果现在我们计算统计的学生的数量,我们该怎么做?

普通成员变量是本类某个对象:


class Student
{
public:
	Student(int num = 0, const char* name = "", char sex = 'm') :m_count(0),m_num(num), m_sex(sex)
	{
		m_name = new char[strlen(name) + 1];
		strcpy_s(m_name, strlen(name) + 1, name);
		m_count++;
	}
	~Student()
	{
		if (m_name != NULL)
		{
			delete[]m_name;
			m_name = NULL;
		}
	}
	void Print()
	{
		cout << "总数" << m_count << endl;
	}
private:
	int m_num;
	char* m_name;
	char m_sex;
	int m_count;
};

void main()
{
	Student s(1001, "张三", 'm');
    s.Print();
	Student s1(1002, "李四", 'f');
	s1.Print();
	Student s2(1003, "王五", 'm');
	s2.Print();
}

我们会发现,三次计算出来的结果都是1,并不是我们所想的1、2、3,这里面的count,每次构造一个心得对象,count都是从0开始计数+1,那我们该怎么让count第一次+1之后第二次构造对象之后计数时从1开始+1得到2呢?

2.全局变量


int m_count=0;
class Student
{
public:
	Student(int num = 0, const char* name = "", char sex = 'm') :m_num(num), m_sex(sex)
	{
		m_name = new char [strlen(name) + 1];
		strcpy_s(m_name, strlen(name) + 1, name);
		m_count++;
	}
	~Student()
	{
		if (m_name != NULL)
		{
			delete[]m_name;
			m_name = NULL;
		}
	}
	void Print()
	{
		cout << "总数" << m_count << endl;
	}
private:
	int m_num;
	char* m_name;
	char m_sex;
};

void main()
{
	Student s(1001, "张三", 'm');
	s.Print();
    Student s1(1002, "李四", 'f');
	s1.Print();
	Student s2(1003, "王五", 'm');
	s2.Print();
}

通过这个我们发现全局变量达到了我们期望的结果,每新构造一个对象,总数加一,但如果一不下心误改了总数,会对结果产生影响吗? 

int m_count=0;
class Student
{
public:
	Student(int num = 0, const char* name = "", char sex = 'm') :m_num(num), m_sex(sex)
	{
		m_name = new char [strlen(name) + 1];
		strcpy_s(m_name, strlen(name) + 1, name);
		m_count++;
	}
	~Student()
	{
		if (m_name != NULL)
		{
			delete[]m_name;
			m_name = NULL;
		}
	}
	void Print()
	{
		cout << "总数" << m_count << endl;
	}
private:
	int m_num;
	char* m_name;
	char m_sex;
};
void Test()
{
	m_count = 10;
}
void fn()
{
	m_count = 20;
}
void main()
{
	Student s(1001, "张三", 'm');
	Student s1(1002, "李四", 'f');
	Student s2(1003, "王五", 'm');
	s.Print();
	Test();
	s1.Print();
	fn();
	s2.Print();
}

 我们发现,s.Print();计算出了最后的总数为三,但经过Test函数后,count被改为10,经过fn函数后又被改为20,那么如果再写一些类似函数,这个count的值会一直被无限修改下去,会出现问题,不能达到我们的目的 error

总结:

全局变量可以实现对象的共享

但是没有权限限制,导致请他的函数或者对象可以无限修改,

则会出现问题(不安全)

3.静态局部变量

void fn()
{
	int a = 0;
	static int b = 0;
	a++;
	b++;
	cout << "a=" << a <<"   " << "b=" << b << endl;
}
void main()
{
	for (int i = 0; i < 5; i++)
		fn();
}

int a = 0;//第二次来的时候,第一次的空间消失了
static int b = 0;//第一次遇到b进行初始化,第二次来的时候之前的空间没有消失(在静态存储

我们发现静态函数再次进入函数没有重新初始化,直接+1,可以用这个解决这个问题。

4.静态数据成员的空间开辟

* 静态数据成员的空间开辟?
*    1.类的声明 .h//多次引用,反复开辟空间
*    2.类的成员函数的定义文件 user.cpp √
*    3.测试文件 test.cpp //用户需分辨,还需开辟空间

class A
{
public:
	//A():m_a(1),m_b(2),m_c(3){}
	A() :m_a(1), m_b(2)
	{
		m_c = 3;//赋值
	}
	void Print()
	{
		cout << m_c << endl;
	}
private:
	int m_a;
	char m_b;
	//static int m_c=20;
	static int m_c;
};
int A::m_c=10;
//int A::m_a = 2;
void main()
{
	cout << sizeof(A) << endl;
	A a;
	A b;
	a.Print();
	b.Print();
	//cout<<A::m_c<<endl;
}

//A():m_a(1),m_b(2),m_c(3){}//m_c不能再构造函数中初始化
m_c = 3;//赋值
//static int m_c=20;//还没有空间
static int m_c;//引用性声明 //不在类中开辟空间,不能在类中进行初始化
int A::m_c=10;//定义性声明 开辟空间
//int A::m_a = 2;//error//只有静态可以
b.Print();// 3 不会因为定义性声明 int A::m_c=10; 而改变
 

 通过A的大小为8我们可以得出,static int m_c;并没有在栈中开辟空间

5.静态数据成员

静态数据成员 实现了本类对象的共享,又实现了限制(类作用域)


class Student
{
public:
	Student(int num = 0, const char* name = "", char sex = 'm') : m_num(num), m_sex(sex)
	{
		m_name = new char[strlen(name) + 1];
		strcpy_s(m_name, strlen(name) + 1, name);
		m_count++;
	}
	~Student()
	{
		if (m_name != NULL)
		{
			delete[]m_name;
			m_name = NULL;
		}
	}
	void Print()
	{
		cout << m_num<<" "<<m_name<<" "<<m_sex<<"总数:" << m_count << endl;
	}
	//static void Show()
	//{
	//	cout << "Show" << endl;
	//	//cout << m_num << " " << m_name << " " << m_sex << "总数:" << m_count << endl;
	//}
	static void Show(Student &s)
	{
		cout << "Show" << endl;
		cout << s.m_num << " " << s.m_name << " " << s.m_sex << "总数:" << m_count << endl;
	}
private:
	int m_num;
	char* m_name;
	char m_sex;
	static int m_count;
	//const int m_i;
	//const static int m_count=20;};
int Student::m_count;
void main()
{
	Student s(1001, "张三", 'm');
	Student s1(1002, "李四", 'f');
	s.Print();
	Student s2(1003, "王五", 'm');
	s1.Print();
	s2.Print();
	s.Show(s);
	Student::Show(s2);
	//Student::Print();
};

//static函数中,没有this指针,所有不能直接输出非static数据成员
    //static void Show()
    //{
    //    cout << "Show" << endl;
    //    //cout << m_num << " " << m_name << " " << m_sex << "总数:" << m_count << endl;
    //}
static int m_count;//不能在成员初始化列表
//const int m_i;//成员初始化列表
//const static int m_count=20;//最好不要这样写,奇怪
s.Show(s);//不管用哪个对象调用static,其实用的是当前对象的类型
Student::Show(s2);//静态可以用类直接调用,不依附对象(不声明对象,也可以调用成员函数)//优点:不用特别声明对象调用函数
    //Student::Print();//非static,有this指针,必须通过对象调用

6.释放

观察以下代码,试想运行结果

#if 0
class A
{
public:
	A() { cout << "A" << endl; }
	~A() { cout << "~A" << endl; }
};
void Test()
{
	static A a;
	//A b;
}
void main()
{
	cout << "main begin" << endl;
	for (int i = 0; i < 5; i++)
		Test();
	cout << "main end" << endl;
}

cout << "main end" << endl;//在这后面即就是程序结束才调用析构

 第一次调用开辟空间,再遇见不开辟空间也不初始化,等程序执行完毕才释放空间

7.总结

1.内存:

静态局部变量在全局数据区分配内存,局部变量在栈区分配内存

2.初始化:

静态局部变量一般在声明处初始化,如果没有显式初始化,会被程序自动初始化为0(局部变量不会执行默认初始化,所以一定要手动初始化,否则会是很奇怪的随机值)

3.最大的优点:

可以和全局变量一样只初始化一次,可以将值保存至下一次函数调用时,而访问范围限定在函数内,不被其他地方访问到(局部变量在栈区,在函数结束后立即释放内存,所以局部变量在每次函数调用时都会被初始化)

4.指针:

普通成员函数有 this 指针,可以访问类中的任意成员;

静态成员函数没有 this 指针,不知道指向哪个对象,所以无法访问对象的成员变量,只能访问静态成员(包括静态成员变量和静态成员函数)

5.释放时机:

 第一次调用开辟空间,再遇见不开辟空间也不初始化,等程序执行完毕才释放空间

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值