前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >++存储类,c++auto关键字,c++ register关键字,c++static关键字,c++mutable关键字,c++thread_local关键字

++存储类,c++auto关键字,c++ register关键字,c++static关键字,c++mutable关键字,c++thread_local关键字

原创
作者头像
高久峰
发布2023-06-23 22:02:48
1230
发布2023-06-23 22:02:48
举报

(1).储存类是干嘛的?第一次听起来以为是面向对象相关的知识,其实不是.它主要用来定义变量或函数的范围,可见性,生命周期。

(2).储存类主要有哪些?

auto (C++17开始被废弃)

register(C++17开始被废弃)

static

extern

mutable

thread_local

(3).auto储存类.声明的变量会自动推断该变量的类型(不需要关注它,毕竟官方已经开始废弃它了)

代码语言:javascript
复制
#include?<iostream>
#include?<typeinfo>
int?main()
{
????auto??a?=?3;
????auto??b?=?"b";
????auto??c?=?3.14;
????auto??d?=?false;
????auto??e?=?new?auto(1024);
????
????//输出a的类型:int
????std::cout?<<?typeid(a).name()?<<?std::endl;
????//输出b的类型:char?const?*
????std::cout?<<?typeid(b).name()?<<?std::endl;
????//输出c的类型:double
????std::cout?<<?typeid(c).name()?<<?std::endl;
????//输出c的类型:bool
????std::cout?<<?typeid(d).name()?<<?std::endl;
????//输出e的类型:int?*
????std::cout?<<?typeid(e).name()?<<?std::endl;
???return?0;
}

可以看到auto储存类和php一样骚,自动类型推断。

(4).register官方解释:储存类用于定义储存在寄存器中而不是RAM中的局部变量。这意味着变量的最大尺寸等于寄存器的大小(通常是一个词),且不能对它应用一元的"&"运算符(因为它没有内存位置)

? ? ?register个人解释:register储存类创建的变量是存放在CPU的寄存器上面,这不同于普通变量在内存上面存放。寄存器中直接读写变量,可以提高效率。但是寄存器空间小,不应该重度依赖。

实例代码:

代码语言:javascript
复制
????register?int?a?=?1;
????std::cout?<<?a;

上面说不能对它使用"&"运算符我测试好像并不对,例如下面的代码进行位运算:

代码语言:javascript
复制
????register?int?a?=?60;
????register?int?b?=?13;
????int?c?=?a?&?b;

????std::cout?<<?c;

(5).static储存类指示编译器在程序的生命周期内保持局部变量的存在,使用static修饰局部变量可以在函数调用之间保持局部变量的值。还是直接上代码吧:

代码语言:javascript
复制
#include?<iostream>
#include?<typeinfo>
using?namespace?std;

//函数声明
void?func();

//static修饰全局变量
static?int?all_count?=?10;

int?main()
{
	//全局变量递减
	while?(all_count--)
	{
		func();
	}

	return?0;
}

void?func()
{
	//static修饰局部变量
	static?int?a?=?0;

	//局部变量递增
	a++;

	std::cout?<<?"全局变量all_count的值为:"?<<??all_count?<<?std::endl;
	std::cout?<<?"局部变量a的值为:"?<<?a?<<?std::endl;
}

首先看修饰全局变量,我去除全局变量的修饰,发现执行结果是一致的。那是不是static修饰全局变量没有意义呢?不是的,static修饰全局变量限制了它的作用域只能在当前的源文件中,避免其他文件使用这个全局变量,其他文件还能命名相同名字的全局变量,不会发生命名冲突。

再看修饰局部变量,假如没有修饰局部变量,那么每次输出的局部变量的值都是1,但是增加了static修饰符,局部变量会记住上次的值,这样值就一直在累计,但是并不能改变它的作用域,它的作用域还是局部的。

(6).extern储存类请参考前面的文章https://www.gaojiufeng.cn/?id=304

(7).mutable储存类暂时未学到面向对象,后面补全

(8).thread_local储存类修饰的变量具有线程周期,什么是线程周期,就是说变量或者对象在线程开始的时候被生成,在线程结束的时候被销毁。

先看代码:

代码语言:javascript
复制
#include?<iostream>
#include?<thread>
using?namespace?std;

//创建thread_local修饰的全局变量
thread_local?int?a?=?1;

//定义方法f
void?f()
{
	a++;
	printf("id:%d,a:%d\r\n",?std::this_thread::get_id(),?a);
}

int?main()
{
	//全局变量自增
	a++;

	//执行f方法
	f();

	//创建线程t1和t2,并设置执行方法为f
	std::thread?t1(f);
	std::thread?t2(f);
	t1.join();
	t2.join();

	return?0;
}

我们发现虽然在主进程/线程中变量a的值已经被修改为3了,并且变量a是全局变量,但是在子进程中变量a的初始化的值都是1。原因就是thread_local修饰符,子进程启动时会复制它的原始值,当然你可以把修饰符去掉再测试。

输出结果为:

代码语言:javascript
复制
id:14532,a:3
id:14252,a:2
id:14152,a:2

我们发现虽然在主进程/线程中变量a的值已经被修改为3了,并且变量a是全局变量,但是在子进程中变量a的初始化的值都是1。原因就是thread_local修饰符,子进程启动时会复制它的原始值,当然你可以把修饰符去掉再测试。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com