c++之——————各种变量

                          对我们程序员来讲,“变量”和“对象”是可以相互互换使用的。-------------开篇之词。

变量:提供一个具有名字的可供程序操作的存储空间。由类型说明符和其后紧跟的数个列表组成,其中变量名之间使用逗号分隔,最后使用分号结尾。像 int sum = 0,value,unit_sold = 0;Sales item;这里的item就是类型为Sales的变量。

对象:是指一块能够存储数据并且具有某种类型的内存空间。

初始化和赋值不是同一概念;初始化是创建变量时赋予其一个初始值,而赋值的含义是把对象的当前值擦除,而用一个新值来替代。自从c++11开始,已经可以使用像int sum{0};这样的初始化了,称为列表初始化!

定义于任何函数之外的变量将被初始化为0;一种例外情况是:定义在函数内部的内置类型变量将不会被初始化。一个未被初始化的内置类型变量的值是未定义的,如果试图拷贝或者以其他形式访问这个类型将会引发错误!!定义于函数体内部的内置类型的对象如果没有初始化,则其值未被定义。类的对象如果没有显示的初始化,则其值由类确定。因此,建议我们初始化每一个内置类型的变量,虽然并非必须这么做,但是如果我们不能确定初始化后程序的运行的安全,那么这么做不失为一种简单可靠地方法--------------养成有变量就初始化的好习惯!!!!

声明规定了变量的类型和名字,但是除此之外还申请了存储空间,也可能会为其变量赋一个初始值。

如果想声明一个变量而非定义它,就在变量前面添加一个关键字extern,而不要显示的初始化变量:extern int i;//声明i而非定义i;int j;//声明并定义j;在函数体内部,如果试图初始化一个由extern关键字标记的变量,将引发错误。变量能且只能被定义一次,但是可以被多次声明!

命名规则:1.用户自定义标示符中不能连续出现两个下划线,也不能使用下划线紧邻大写字母开头,定义函数体以外的标识符不能以下划线开头!

              2.变量名要写成小写,方便阅读。

              3.用户自定义的类型一般要以大写字母开头。

              4.如果标识符由多个单词组成,则单词间应该有明显区分。

建议:当你第一次使用变量时再定义它;也就是说,再对象第一次被使用的地方附近定义它是一种好的选择,因为这样做有助于更加容易地找到变量的定义。更重要的是,当变量的定义与它第一次被使用的地方很近时,我们也会赋予它一个比较合理的初始值!

复合类型:是指基于其他类型定义的类型。主要有:引用和指针。

引用:为对象起的另一个名字,引用类型引用另外一种类型,通过将声明符写成&d的形式来定义引用类型,其中d是声明的变量名。例如;

                 int ival = 1024;

                 int &refval = ival;//refval 指向ival(是ival的另一个名字)

                 int &refval2;//报错,引用必须被初始化。

引用并非对象,相反的,他只是为一个一个已经存在的对象所起的另外一个名字。

指针:是指向另外一种类型的复合类型。也是实现对其他对象的间接访问。

定义指针类型的方法将声明符写成*d的形式,其中d是变量名。如果在一条语句中定义了几个变量,每个变量前面都必须有符号*。

int *ipa,*iP1;

double *db2;//db2是指向double型对象的指针。

指针是存放某个对象的地址,要想获取该地址,需要使用取地址符(&)。

int ival = 42;

int *p = &ival;//p存放变量ival的地址,或者说p是指向变量ival的指针。

建议,初始化所有指针;在大多数编译器环境下,如果使用了未经初始化的指针,则该指针所占内存空间的当前内容将被看成是一个地址值。访问该指针,相当于去访问一个根本不存在的位置上的本不存在的对象。但是如果指针所指内存空间恰好有内容,而这些内容有被当作了某个地址,我们就根本无法分清他是合法还是非法的了。因此建议,初始化所有指针,并在可能的情况下,尽管等定义了对象之后再定义指向它的指针。如果实在分不清应该指向何处,就把它初始化为nullstr或者0,这样的话,程序就能检测并知道它没有指向任何具体的对象了。

任何非0指针对应的条件都是true,如果指针的值是0,那么条件取false。

多个变量的定义。经常出现错误的是如下下情况:

在声明指针时,将空格写在类型修饰符合变量名之中间。int* p;这个情况可能产生误导是因为int*放在一起,让人想到这条语句中所有变量共同的类型一样。其实这样认为是错的。基本数据类型仍然是int而不是int*。*仅仅是修饰p而已,对生命语句中其他变量,它并不起任何作用。例如int* p1,p2;p1是指向int的指针,p2是int型。因此我们要记住,一定将变量标识和修饰符写在一起。这种形式注重强调变量具有的复合类型。

指向指针的指针:

通过*的个数可以区分指针的区别,**表示指向指针的指针,***表示指向指针的指针的指针。

int ival = 1024;

int *pi = &ival;

int **pii = π//ppi指向一个int型的指针。

它们的关系如下:

ppi---〉pi---〉ival

解引用int型指针会得到一个int型数,同样,解引用指向指针的指针得到一个指针,此时要访问最原始的那个对象,需要对指针做两次解引用。

指向指针的引用:

引用本身不是一个对象,因此不能定义指向引用的指针。但是指针是对象,所以存在对指针的引用:

int i= 42;

int *p;//p是一个int型指针

int *&r = p;//r是一个对指针p的引用。

 

r = &i;//r引用了一个指针,因此给r赋值&i就是令p指向i;

*r = 0;//解引用r得到i,也就是p指向的对象,将i的值改为0.

const限定符:

注意,因为const对象一旦创建后其值不能再改变,所以const对象必须初始化。初始化可以是任意复杂的表达式。

const int i= get_size();//正确,运行时初始化。

const int j = 42;//正确,编译时初始化。

const int k;//错误,k是一个未经初始化的常量。

下面很多人是很容易迷惑的,详解:

在不改变const对象的操作中还有一种是初始化,如果利用一个对象去初始化另外一个对象,则他们是不是const都无关紧要。

int i= 2;

const int ci = i;//正确,i的值被拷贝给了ci

int j = ci;//正确,ci的值被拷贝给了j。

尽管ci是常量,但是无论如何ci中的值还是一个整形数。ci的常量特征仅仅在执行改变ci的操作时才发挥作用。当用ci去初始化j时,根本无需在意ci是不是一个常量。拷贝一个对象的值并不会改变它,一旦拷贝完成,新的对象就和原来的对象没有什么关系。

在编译const变量时,把用到该变量的地方都替换成对应的值。比如const int i = 512;那么在别的地方出现这个i变量,将会全部用512直接替换。

如果程序包含多个文件,则每个用了const对象的文件都必须得能访问到它的初始值才行。要做到这一点,就必须在每个用到变量的文件中都对它进行定义。默认情况下,const对象被设定为仅在本文件内有效。当多个文件中出现了同名的const变量时,其实等同于在不同文件中分别定义了独立的变量。

如果想要让const变量具有在文件间被共享的特点;也就说,只在一个文件中定义const,而在其他多个文件中声明并使用它。解决的办法是:

对于const变量不管是声明还是定义都添加extern关键字,这样只需定义一次就行;

//file.cpp定义并初始化了一个常量,该常量能被其他文件访问。

extern const int bufsize = fcn();

//file.h头文件

extern const int bufsize;//这里的bufsize与file.cpp文件中定义的是同一个。

注意:如果想在多个文件之间共享const对象,必须在变量的定义之前添加extern关键字。

对常量的引用:对常量的引用不能被用作修改它所绑定的对象:

const int ci = 204;

const int &r1 = ci;//正确:引用及其对应的对象都是常量。

r1 = 42;//错误,r1是对常量的引用

int &r2 = ci;//错误,试图让一个非常量引用一个常量对象。

指针和cosnt

指针可以指向常量和非常量。类似于常量引用。指向常量的指针不能用于改变其所指对象的值。要想存放常量对象的地址,只能使用指向常量的指针:

const double pi = 3.14;//pi是个常量,它的值不能改变

double *ptr = π//错误,ptr是一个普通指针、

const double *cptr = π//正确,cptr可以指向一个双精度的指针。

*cptr = 42;//错误,不能给*cptr赋值。

const指针

 大家都知道,指针是对象,但是引用却不是对象。因此允许指针本身定为常量。常量指针必须初始化,而一旦初始化,则它的值就不能再改变了。把*放在const关键字之前用以说明指针是个常量,这样写隐含着深层次的意思:不变的是指针本身的值,而不是指向的那个值。

int errNumb = 0;

int *const curErr = &errNumb;//curErr将一直指向errNumb

const double pi = 3.1415;

const double *const pip = π//pip是一个指向常量对象的指针。

字面值类型:

目前接触的数据类型中,算术类型、引用和指针都属于字面值类型。这些可以被定义为constexpr。即使引用和指针都能定义为constexpr,但是收到严格限制。一个constexpr指针的初始值必须是nullptr或者0,或者是存储在某个固定地址中的对象。

另外,定义于函数体内的变量一般来说并非存放在固定的地址中的,因此constexpr指针不能指向这样的变量。相反,定义于所有函数之外的对象其地址是固定不变的,能用来初始化constexpr指针。此外,允许函数定义一类有效范围超出函数本身的变量,这类变量和定义在函数体外的变量一样也有固定的地址。因此,constexpr引用能绑定到这样的变量上,constexpr指针也能指向这样的变量。

 

posted @ 2015-08-25 19:49  深入理解C++和OpenCV  阅读(530)  评论(0编辑  收藏  举报