c++ primer(二)

来源:互联网 发布:淘宝规定多长时间发货 编辑:程序博客网 时间:2024/06/06 20:36

(13)指针与引用区别

第一,指针本身是对象,允许对指针赋值和拷贝,而且在指针的生命周期内,它可以先后指向几个不同的对象

第二,指针无需在定义时赋初值

(14)空指针:不指向任何一个对象。

c++11:得到空指针最直接的办法是用字面值nullptr初始化指针,它可以被转换成任意其他的指针类型

int *p1 = nullptr;int *p2 = 0;//#include cstdlibint *p3 = NULL;

(15)预处理器上运行于编译过程之前的一段程序,预处理变量不属于命名空间啊std,由预处理器负责管理,因此无需在前边加上std::

当用到预处理变量时,预处理器会自动将它替换为实际值

(16)void* 指针,可用于存放任意对象的地址

利用它做的事比较有限:与其他指针做比较;作为函数的输入输出;

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

阅读方法:从右向左阅读r的定义。离变量名最近的符号对变量类型最有直接的影响。

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

(18)const 限定符

默认状态下,const对象仅在文件内有效。当多个文件中出现了同名的const变量时,其实等同于在不同文件中分别定义了独立的变量。

编译器将在编译过程中把用到变量的地方替换成对应的值

如果想在一个文件中定义const,在其他文件中声明并使用它,则需要在const变量前,无论声明还是定义都要添加extern关键字,

//file_1.cextern const int bufsize = fcn();//定义初始化一个常量,可以被其他文件访问//file_1.hextern const int bufsize;//与file_1.c中定义的是同一个


(19)引用的类型必须与其所引用对象的类型一致,但是有两种例外

第一种,初始化常量引用时允许用任意表达式作为初值,只要该表达式的结果能转换成引用的类型即可。尤其,允许一个常量引用绑定非常量的对象、字面值、一般表达式。

int i = 42;const int &r1 = i;//正确const int &r2 = 42;//正确const int &r3 = r1*2;//正确int &r4 = r1*2;//错误,r4是一个普通的非常量引用
一个常量引用被绑定到另一种类型上,错误的原因

double dval =3.14;const int &ri = dval;

编译器把上述代码变成如下形式:

const int temp = dval;//由双精度生成一临时整型常量const int &ri =temp;//让ri绑定个临时量

ri绑定一个临时量对象temp,而非dval;既然让ri绑定dval,肯定想通过ri改变dval,否则为什么要给ri赋值呢。因此c++将这种行为列为违法。

第二种,对const的引用可能引用一个并非const的对象

int i = 42;int &r1 = i;cosnt int &r2 = i;r1 =0;r2 =0;//错误

(20)指向常量的指针:不能用于改变其所指对象的值。要想存放常量对象的地址,只能使用指向常量的指针。

            const指针:必须初始化,一旦初始化完成,则它的值不能改变,把*放在const之前,说明他是一个常量。int *const curErr;

(21)顶层const:指针本身是个常量

      底层const:指针所指的对象是个常量

当对象进行拷贝操作时,拷入和考出的对象必须具有相同的底层const资格

(22)常量表达式,值不会改变并且在编译过程中就能得到计算结果的表达式

const int max_files = 20;//是const int limit = max_files + 1;//是int staff_size = 29;//不是const int sz = get_size();//不是,尽管sz本身是个常量,但是它的值直到运行时才能获得,所以它不是常量表达式

constexpr变量:c++11允许将变量生命为constexpr类型以便编译器可以来验证变量的值是否为一个常量表达式。

constexpr int mf = 20;//constexpr int limit = mf +1;//constexpr int sz = size();//只有当size是一个constexpr函数时,才是一条正确的声明语句

(23)类型别名

typedef

suing SI = sales_item;

(24)auto类型说明符

c++11中引入auto,它能让编译器替我们去分析表达式所属类型。

auto i =0,*p = &i;//正确auto sz = 0, pi = 3.14;//错误,sz,pi类型不一致

auto类型有时候和初值类型并不完全一样,编译器会适当地改变结果类型使其更符合初始化规则。

int i =0, &r = i;//auto a =r; //a是一个整数(r是别名,而i是一个整数)

auto一般会忽略掉顶层const,同时底层const 则会保留下来

int i=0;const int ci = i,&cr = ci;auto b = ci; //b是一个整数(ci顶层const忽略掉了)auto c = cr; //c是一个整数(cr是ci别名,ci本身是顶层const)auto d = &i;//d是整型指针(整数的地址就是指向整数的指针)auto e =&ci;//e是指向整数常量的指针

如果希望推断出auto是个顶层const,需要明确指出

const auto f = ci;//ci的推演类型是int,f是const int
将引用类型设为auto,原来初始化规则仍适用

auto &g = ci; //g是一个整型常量引用,绑定到ciauto &h =42; //错误,不能为非常量引用绑定字面值const auto &j = 42; //正确,可以为常量引用绑定字面值

(25)decltype类型指示符:选择并返回操作数的数据类型(包括顶层const 和引用在内),如果使用的表达式不是一个变量,则返回表达式结果对应的类型。

//decltype的结果可以是引用类型int i = 42;*p = &i, &r =i;decltype(r+0) b;    //正确,加法的结果是int,因此b是一个未初始化的b。decltype(*p);        //错误,c是int&,必须初始化

r是一个引用,因此decltype(r)的结果是引用类型。如果想让结果类型是r所指的类型,可以把r作为表达式的一部分,如r+0,显然这个表达式的结果将是一个具体值而非一个引用

如果表达式的内容是解引用操作,则decltype得到引用类型。

decltype使用的是一个不加括号的变量, 得到的结果就是该变量的类型;

如果加上了一层或者多层括号,编译器会把他当成一个表达式。

decltype((i)) d;//错误:d是int&,必须初始化decltype(i) e;   //正确,e是一个未初始化的int

decltype((variable)) 的结果永远是引用

decltype(variable)的结果只有当variable本身就是一个引用时才是引用



原创粉丝点击