C++变量类型

来源:互联网 发布:宋神宗资治通鉴序 知乎 编辑:程序博客网 时间:2024/06/14 10:14

全局变量

全局变量不受作用域影响
如果在一个文件中使用extern关键字来声明另一个文件中存在的全局变量,那么这个文件可以使用这个数据(即另一个文件中使用已存在文件中的变量,两者共用一个变量)

//**test1.cpp:**#include <iostream>using namespace std;//声明int globe;void f();int main(){    globe=12;    cout<<globe<<std::endl;    f();    cout<<globe<<std::endl;    return 0;}//**test2.cpp**extern int globe;void f(){    globe=47;}

test1.cpp和test2.cpp是分段编译的,必须通过声明extern int globe来告诉编译器变量存在哪里。
创建后的程序,带有test2的目标文件必须被连接起来,test2
不会生成可执行文件,编译它是为了把它连接进来其他的可执行文件中。

局部变量

局部变量出现在一个作用域内,他们是局限于一个函数的,局部变量被称为自动变量,因为它们在进入作用域时自动生成,离开作用域时在自动消失,关键字auto可以显示的说明这个问题,但是局部变量默认为auto,所以没有必要声明为auto
寄存器变量:是一种局部变量,关键字register告诉编译器“尽可能快的访问这个变量”,加快访问速度取决于实现,通常通过在寄存器中放置变量来实现。–>并不保证一定将变量放在寄存器中,甚至不能保证提高访问速度,这只是对编译器的一个请求或暗示。

静态变量

1、局部变量用static修饰,即可以使得局部变量的值在整个程序的生命周期中里仍然存在。

#include <iostream>using namespace std;void func(){    static int i=0;    cout<<"i = "<<i++<<std::endl;}int main(){    for(int x=0;x<10;x++){        func();    }    return 0;}

2、当应用static于函数名和所有函数外部的变量时,它的意思是“在文件的外部不可以使用这个名字”即函数名或变量是局部于文件的,所以static具有文件作用域。即使被声明为extern,连接器也不会找到该变量,用了static之后,该变量仅限于在本cpp中使用。

外部变量

extern关键字:告诉编译器存在着一个变量和函数,即使编译器在当前编译的文件中没有看到它。这个变量或函数可能在另一个文件中或者在当前文件的后面定义。
如下图例子:extern int i其实不是定义变量,而是告诉编译器,该变量会在当前文件后面或者另一个文件中已经定义了。

#include <iostream>using namespace std;extern int i;extern void func();//extern关键字:这个变量或函数可能在另一个文件中或者在当前文件的后面定义。int main(){    i=0;    func();}int i;//数据定义void func(){    i++;    cout<<i;}

常量

在旧版本的C中,如果相建立一个常量,必须使用预处理器

#define PI 3.1415926;`

对名字PI不会进行类型检查(即预处理之后程序中遇到PI的就换成3.1415926,预处理定义常量无需写是什么类型的数据),也不能得到PI的地址(所以不能向PI传传递一个指针和一个引用),PI不能是用户定义的类型变量。预处理器并不识别作用域(预处理即为预先处理,在程序编译之前就进行了,所以没有啥作用域)。

使用const关键字
const就像正常的变量一样有作用域。
在C中定义const时,如果咋两个不同的文件中(或在头文件中),定义多个同名的const,编译器将生成发生冲突的错误消息。
在C中使用const和在C++中使用是完全不一样的,在C++中使用更好。
在C++中,const变量必须有初始值(在C中不是这样),内部类型的常量值可以表示为十进制、八进制、十六进制、浮点数或字符
常量值钱带0:八进制
常量值钱带0x:十六进制
浮点数可以含有小数或指数幂(用e表示,意思是10的幂)

volatile变量

volatile告诉编译器“不知道何时会改变”,防止编译器依据变量的稳定性作任何优化
如果一个标识符是voliate的,编译器不会认为它能够对标识符的多次读入进行优化,即多线程读取一个数据时,会观察该数据是否正在被另一个标识符或进程修改,即为保证可见性,是轻量级的同步,保证每次都从内存中读取数据。

java中的volatile
volatile和synchronize有本质的区别

  • 用一句话概括volatile,它能够使变量在值发生改变时能尽快地让其他线程知道.
  • 同步:如用synchronized关键字,或者使用锁对象.

volatile关键字保证的是可见性,是字段关键字,不像synchronize还可以修饰方法和类。
volatile关键字保证字段每次都是从堆内存中读取,当字段在栈中进行多线程操作时,随机进入的每个线程必须从堆内存中读取该字段到栈中进行操作,操作完成再放回堆中,这样就可以保证每个线程读取到的字段是最新值。
(个人理解:volatile关键字让字段像引用类型数据一样,存放在堆中,让原本在多线程环境下字段copy给每个线程使用的,变成了线程都得从堆中寻址字段。一般一个类的基本类型数据操作时就是把数据copy给线程栈使用的,而加了volatile之后,就直接像引用类型一样操作了。)

首先我们要先意识到有这样的现象,编译器为了加快程序运行的速度,对一些变量的写操作会先在寄存器或者是CPU缓存上进行,最后才写入内存.
而在这个过程,变量的新值对其他线程是不可见的.而volatile的作用就是使它修饰的变量的读写操作都必须在内存中进行!

  • volatile本质是在告诉jvm当前变量在寄存器中的值是不确定的,需要从主存中读取,synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住.
  • volatile仅能使用在变量级别,synchronized则可以使用在变量,方法.
  • volatile仅能实现变量的修改可见性,但不具备原子特性,而synchronized则可以保证变量的修改可见性和原子性.
  • volatile不会造成线程的阻塞,而synchronized可能会造成线程的阻塞.
  • volatile标记的变量不会被编译器优化,而synchronized标记的变量可以被编译器优化.

所以从一定意义上说,voliate相当于轻量级的synchronize。
但不同的是,volatile关键字不是给字段加锁,只是把字段读取区域固定在主内存区并不阻塞控制线程的进入,该字段下的多线程环境还是随机的,并不能保证一个数据不会被多个线程并发修改(voliate关键字并不能控制线程等待、阻塞、唤醒等,更不能让线程序列执行)。

synchronize关键字保证的就是同步互斥。
synchronize和volatile最大的区别就是是否为线程加锁。

0 0
原创粉丝点击