(1).储存类是干嘛的?第一次听起来以为是面向对象相关的知识,其实不是.它主要用来定义变量或函数的范围,可见性,生命周期。
(2).储存类主要有哪些?
auto (C++17开始被废弃)
register(C++17开始被废弃)
static
extern
mutable
thread_local
(3).auto储存类.声明的变量会自动推断该变量的类型(不需要关注它,毕竟官方已经开始废弃它了)
#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的寄存器上面,这不同于普通变量在内存上面存放。寄存器中直接读写变量,可以提高效率。但是寄存器空间小,不应该重度依赖。
实例代码:
register int a = 1; std::cout << a;
上面说不能对它使用"&"运算符我测试好像并不对,例如下面的代码进行位运算:
register int a = 60; register int b = 13; int c = a & b; std::cout << c;
(5).static储存类指示编译器在程序的生命周期内保持局部变量的存在,使用static修饰局部变量可以在函数调用之间保持局部变量的值。还是直接上代码吧:
#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://blog.20230611.cn/?id=304
(7).mutable储存类暂时未学到面向对象,后面补全
(8).thread_local储存类修饰的变量具有线程周期,什么是线程周期,就是说变量或者对象在线程开始的时候被生成,在线程结束的时候被销毁。
先看代码:
#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修饰符,子进程启动时会复制它的原始值,当然你可以把修饰符去掉再测试。
输出结果为:
id:14532,a:3 id:14252,a:2 id:14152,a:2
我们发现虽然在主进程/线程中变量a的值已经被修改为3了,并且变量a是全局变量,但是在子进程中变量a的初始化的值都是1。原因就是thread_local修饰符,子进程启动时会复制它的原始值,当然你可以把修饰符去掉再测试。
c#中string和StringBuilder直接看看执行速度。(2).String类型累计赋值Test  ...
【一】.钩子文件的设置和创建(1).打开hooks目录,可以看到有一个post-commit.tmpl文件,这是一个模板文件。复制一份,重命名为post-commit,将其用户组设为www,并设置为可执行。chown www:www post-commitchmod +x post-commit(2...
1.全局用户信息设置 git config --global user.name gaojiufeng git config --global user.email 392223903...
1.远程仓库的协作模式开发者把自己最新的版本推到线上仓库,同时把线上仓库的最新代码,拉到自己本地即可2.注册git帐号国外: http://www.github.com国内: http://git.oschina.net2.在码云创建项目,不要初始化readmegit push https://gi...
日志查看:git log版本切换:方式1:git reset --hard HEAD^ 倒退一个版本git reset --hard HEAD^^ 倒退两个版本方式2:(版本号的形式,建议版本号码补充完...
1.关机Process.Start("shutdown", "-s -t 0"); 2. 注销 Proc...