如果表达式里既有带符号类型又有无符号类型,当带符号类型取值为负时会出现异常结果。因为带符号数会自动转换成无符号数。
unsigned u=10;int i=-42;std::cout<<i+i<<std::endl;//输出-84std::cout<<u+i<<std::endl;//如果int占32位,输出4294967264引用与指针:
引用并非对象,引用只是为一个已经存在的对象所起的另外一个名字。
指针本身就是一个对象,允许对指针赋值和拷贝,而且在指针的生命周期内它可以先后指向不同的对象。
指针无需再定义时赋初值。但是在块作用域定义内的指针一定要初始化。
利用相等操作符(==)或!=操作符比较指针时,比较的是两个指针存放的地址值。
指向指针的引用:
引用本身不是一个对象,因此不能定义指向引用的指针。但指针是对象,所以存在对指针的引用。
int i=42;int *p=0;//p是一个int型指针int *&r=p;//r是一个对指针p的引用r=&i;//令p指向i*r=0;//令解引用r得到i,i=0;面对一条比较复杂的指针或引用的声明语句时,从右到左阅读有助于弄清楚它的真实含义。
const的引用:
常量引用仅对引用可参与的操作做出了限定,对引用的对象本身是不是一个常量未作限定。
const的指针:
指向常量的指针不能用于改变其所指对象的值。要想存放常量对象的地址,只能使用指向常量的指针。
const double pi=3.14;//pi是一个常量,值不能被改变double *ptr=π//错误,ptr是一个普通的指针const double *cptr=π//指向常量的指针指向一个常量对象*ptr=42;//错误,不能给*ptr赋值double dval=3.14;cptr=&dval;//正确,见note.Note: 指向常量的指针没有规定其所指对象必须是一个常量。所谓指向常量的指针仅仅要求不能通过该指针改变对象的值,而没有规定那个对象的值不能通过其他途径改变。
const指针
常量指针表示指针本身是一个常量,其必须初始化,而且一旦初始化完成,则它的值,也就是存放在指针中的那个地址就不能再改变。表示为* const,不变的是指针本身的值,而非指向的那个值。
int errNumb=0;int *const currErr=&errNumb;//currErr一直指向errNumbconst double pi=3.14159;const double *const pip=π//pip是一个指向常量对象的常量指针*pip=2.172;//不能通过指针修改对象的值,因指向常量对象*curErr=0;//可以把curErr指针指向的对象重置,因其指向非常量对象。顶层const表示指针本身是一个常量。
底层const表示指针所指对象是一个常量。
int i=0;int *const p1=&i;//顶层constconst int ci=42;//顶层constconst int *p2=&ci;//底层const当执行对象的拷贝操作时,常量是顶层const还是底层const区别明显。
顶层const不受什么影响。
i=ci;//正确p2=p3;//正确当执行对象的拷贝操作时,拷入和拷出对象必须具有相同的底层const资格,或者两个对象的数据类型必须能够转换。
int *p=p3;//错误,p3包含底层const的定义,而p没有p2=p3;//正确p2=&i;//正确,int*能转化成const int*int &r=ci;//错误,普通的int&不能绑定到int常量上const int &r2=i;//正确:const int&可以绑定到普通的int上constexPR和常量表达式:
常量表达式是值不会改变并且在编译过程就能得到计算结果的表达式。
我们允许将变量声明为constexpr类型以便由编译器来验证变量的值是否是一个常量表达式。声明为constexpr的变量一定是一个常量,而且必须用常量表达式初始化。
在constexpr声明中如果定义一个指针,限定符constexpr仅对指针有效,与指针所指的对象无关。
const int *p=nullptr;//p是一个指向整型常量的指针constexpr int *q=nullptr;//q是一个指向整数的常量指针需要注意的是,const是给定类型的修饰。当使用类型别名的时候,类型别名就是一个类型。
typedef char *pstring;//pstring是char*const pstring cstr=0;//cstr是指向char的常量指针const pstring *ps;//ps是一个指针,它的对象是指向char的常量指针C++11新标准引入了auto类型说明符,用它就能让编译器替我们去分析表达式所属的类型。
(1)推断引用时,编译器以引用对象的类型作为auto的类型。
(2)auto 一般会忽略掉顶层const,同时底层const则会保留下来。
(3)如果我们希望推断出的auto类型是一个顶层const,需要显式指出。
decltype类型指示符:选择并返回操作数的数据类型。
decltype(f()) sum=x;//sum的类型就是函数f的返回类型。编译器分析表达式并得到它的类型,却不实际计算表达式的值如果decltype使用的表达式是一个变量,则decltype返回该变量的类型(包括顶层const和引用在内)。
const int ci=0,&cj=ci;decltype(ci) x=0;//x的类型是const intdecltype(cj) y=x;//y的类型是const int&,y绑定到变量xdecltype(cj) z;//错误,z是一个引用,必须初始化。如果decltype使用的表达式不是一个变量,则decltype返回表达式结果对应的类型。
int i=42,*p=&i,&r=i;decltype(r+0) b;//正确:加法的结果是int,因此b是一个(未初始化的)intdecltype(*p) c;//错误,c是int&,必须初始化。如果表达式的内容是解引用操作,则decltype将得到引用类型。decltype((variable)) (注意是双层括号)的结果永远是引用,而decltype(variable)结果只有当variable本身就是一个引用时才是引用。
decltype((i)) d;//错误:d是int &,必须初始化decltype(i) e;//正确:e是一个(未初始化的)int新闻热点
疑难解答
图片精选