【C++语言99个常见编程错误】第2章 语法问题

2章 语法问题

数组定义和值初始化的语法形式混淆

int *ip = new int(12); ip指向的是单个的一个整数

int *ip = new int[12]; 正确的内存申请方法

最好的内存申请形式就是根本不去申请,直接用标准库的组件:Vector或者其他

捉摸不定的评估求值顺序

函数参数的求值没有固定的顺序,必须手动消除这样的副作用

子表达式的求值次序也不一样,运算符的优先级和结合性对求值次序没有影响

new会比类型的构造函数先调用,先为对象拿到存储,再在这个存储上初始化它

逗号,三目运算符有求值顺序的

逻辑运算符&&||有短路特性,也算是有顺序么?YEP

运算符的优先级问题

C++中,没有非结合的运算符

a>b>c,合法,但可能词不达意

取大优先解析原则带来的问题

词法分析引入取大优先解析原则:尽可能取长的字符序列作为词法单位

a+++++b是非法的,它被解析为a++ ++ +b

list> lovos也是错的,list 空格> lovos

声明修饰符次序的小聪明

先写连接修饰词,再写量化修饰词,再写类型

extern const int size = 1024

指向常量的指针有两种声明形式:

const int *pc;

int const *pc;

“函数还是对象”的多义性

对象的默认初始化语句不应该写成一个空的初始化参数列表的形式,因为它会被解释成一个函数声明。如String x()

该多义性在new表达式中并不发作:String *p = new String(),可以

效果漂移的类型量化饰词

内建数组不可能有constvolatile,所以修饰它的类型量化饰词(constvolatile)的效果实际上会漂移,转而应用到其持有物的某个适当位置

量化饰词的实际效果会转移到数组的元素上去了

自反初始化

int var = 1;

{

double var = var,编译通过,但行为未定义,右边用到的var正是刚刚声明的

}

const int var = 1;

{

enum{var = var};

}

这是可以的,枚举的声明位置,与变量不同,是在它的初始化对象(枚举的定义)之后的。后面一个var是外层作用域中的常量。

静态连接类型和外部连接类型

根本没有本条款名称所说的这种东西。

连接类型饰词总是绑定到对象或函数,而不是类型。

static class R

{} r; //静态的

R r2;//非静态

匿名名字空间

namespace{

R r2;

R r;

}

这样,rr2就有了外部连接类型,能有比用static修饰用在更多的地方,而且就像静态对象一样,它们在当前编译单元以外的地方不可访问

运算符函数名字查找的反常行为

当我们记不住中序记法时,函数调用更清晰

a = b;

a.operator = (b)

中序和函数调用的名字查找顺序不一样

晦涩难懂的operator->

内建的operator->是二元的,重载版本的operator->是一元的。对于重载的operator->的调用,必须返回一个可以用(内建的)operator->访问其成员的

operator->的调用序列的触发总是由包含operator->之定义的对象静态决定的,而且该调用顺序总是终结于返回指向class对象的内建指针的调用

 

你可能感兴趣的:(C++语言99个常见编程错误)