1、 C++提供了丰富的操作符,定了了操作数为内置类型时操作符的含义。此外,C++还支持操作符重载,允许自定义用于类类型时操作符的含义。
2、 对于含有操作符的表达式,其值通过对操作数做制定操作而获得。除了特殊的用法外,表达式的结果是右值,可以读取,但不允许对其进行赋值。
3、 操作符的含义:该操作符执行什么类型的操作以及操作结果的类型——取决于操作数的类型。
4、 C++一元操作符和二元操作符、三元操作符:有些符号既可以作为一元操作符,也可以作为二元操作符。(*)
5、 操作符对操作数的类型有要求,如果操作符用于内置类型或者复合类型,则由C++语言定义其类型要求。
6、 对于除法(/)和求模(%):a、 两操作数为正,结果也为正;b、两操作数为负,除法结果为正,求模为负;c、一正一负,除法的结果为负,但上取整还是下取整取决于机器,求模的符号取决于机器。
7、 不应串接使用关系操作符,但是实际上串接使用是不违背语法规则的。
8、 移位操作符用于IO:重载的操作符与该操作符的内置类型版本有相同的优先级和结核性。IO操作符为左结合。
9、 赋值:下标和解引用操作符都返回左值,当将这两者操作用于非const数组时,结果可以作为赋值操作的左操作数。赋值表达式的值是左操作数的值。赋值操作符也返回左值。
10、赋值操作符的右结合性:a = b = 1;
int a, *p;
a = p = 0;//错误:a和p类型不同,虽然都0可以赋值给这两个变量。
11、 赋值操作符的优先级低于不等号。
12、 复合赋值操作符: +=, -=, *=, /=, %=, <<=, >>=, ^=, |=, 没有~=(求反,只有一个操作数)。
13、 自增自减:前置操作返回加1以后的值,所以返回对象本身,是左值;后置操作返回的是右值,即返回的是变量原来的值。
14、 只有在必要的时候才使用后置操作符:前置操作要做的工作更少,尽量使用前置操作符。
15、 后自增操作符的优先级高于解引用: *it++,等价于*(it++), 表达式it++返回的是it原来的值。后自增操作符返回其操作数原值的副本。
16、 简洁即美。
17、 点操作符的优先级高于解引用。箭头操作符->
18、 条件操作符:C++中唯一的三元操作符条件操作符的优先级相当低。
cout << (i < j) ? i : j;
等价于:
cout << (i < j);
cout ? i : j;
19、 sizeof操作符:返回一个对象或类型名的长度。
Sales_item it, *p;
sizeof(Sales_item);
sizeof it ;
sizeof *p;
以上三者等价。sizeof *p中,指针p可以持有一个无效地址,因为不需要对p做解引用操作。
20、 数组和指针的不同:指针指向数组的时候,指针解引用返回数组第一个元素,数组解引用返回的也是第一个元素。但是对指针用sizeof操作符操作的结果是指针的大小,而对数组用sizeof操作符,则返回的是数组的大小。
int ar[4] = {1, 2, 3, 4}, *pi = ar;
cout<<"sizeof(ar)="<<sizeof(ar)<<",sizeof(*ar)="<<sizeof(*ar)<<", *ar="<<*ar<<endl;
cout<<"sizeof(pi)="<<sizeof(pi)<<",sizeof(*pi)="<<sizeof(*pi)<<", *pi="<<*pi<<endl;
运行结果如下:
21、 逗号表达式:从左向右计算,结果是其最右边表达式的值。
22、 操作符的优先级和结合性:当操作符优先级相同时,由结合性决定求解次序,算数操作符有左结合性,因此从左向右计算。C++规定了操作数的计算顺序的操作符有:||, &&, 以及条件操作符和逗号操作符。除此之外,其他操作符并未指定操作数的求值顺序。
例如:f1()*f2(), 先调用哪个是未知的。
23、 new和delete:如果不提供显式初始化,动态创建的对象与在函数内定义的变量的初始化方式相同。对于类类型的对象,用默认构造函数进行初始化,内置类型则无初始化。delete删除指针所指向的地址空间。如果指针指向不是由new分配的内存地址,则该指针上使用delete是不合法的。
24、 动态内存管理容易出错:删除指向动态分配内存的指针失败,而无法将内存块返还给自由存储区,则为内存泄露,只有等耗尽内存才会显露出来。读写已经删除的对象也容易出错,最好是删除指针指向的对象以后,将指针置为0值。对同一个内存空间使用两次delete表达式,则自由存储区可能会被破坏。
25、 尽管不能改变const对象的值,但是可以删除const动态对象。
26、 类型相关:如果两个类型之间可以相互转换,则称这两个类型为类型相关。
27、 隐式类型转换:a、 在混合类型的表达式中,操作数被转换为相同的类型; b、 用作条件的表达式被转化为bool类型; c、 用一表达式初始化某个变量,或将一表达式赋值给某个变量,则该表达式转化为变量的类型。d、 函数调用中也可能发生隐式类型转换。
28、 算数转换:保证在执行操作之前将二元操作符的两个操作数转换为同一个类型,并且表达式的值也具有相同的类型。
29、 整型提升:对于所有比int小的整型,如char、signed char、unsigned char、short、unsigned short,如果该类型的所有可能的值都能包容在int内,则他们会被提升为int型,否则会被提升为unsigned int,bool提升为int,false 为0, true为1。
30、 如果int足以表示所有的unsigned short,则转换为int,否则将unsigned short转换为unsigned int,以保护精度。long和unsigned int也是一样的。
31、 对于包含signed和unsigned int类型的表达式,现将signed转化为unsigned,如果signed为负数,则将signed对该类型取值个数取模而转化为unsigned。
32、 其他隐式转换:
a、指针转换:数组转化为指向第一个元素的指针; b、转换为bool类型; c、 算数与bool类型转化; d、 枚举类型转换为整形,enum对象至少提升为int,如果int不够表达其最大值,则转化为unsigned int、long或者unsigned long; e、转化为const对象; f、 类类型可以定义由编译器自动执行的类型转化,如cin>>s, 返回ifstream对象,在while(cin>>s)时转化为bool。
33、 显式转换:强制类型转换, static_cast, dynamic_cast, const_cast, reinterpret_cast;
double dval;
int ival;
ival *= dval;//两次转化,ival->double,结果->int
ival *= static_cast<int>(dval);//一次转化
34、 命名的强制类型转化符号:cast-name<type>(expression);
a、 dynamic_cast支持运行时识别指针或引用所指向的对象;
b、 const_cast将换掉表达式的const性质:
const char *pc_str;
...
char *pc = string_copy(const_cast<char*>(pc_str);
c、static_cast:编译器隐性执行的任何类型转化都可以由static_cast来显式完成。对于从一个较大类型转化为较小的类型时,编译器通常会提出警告,但是如果显式提供强制类型转化,则警告会关闭。
d、 reinterpret_cast:为操作数的为模式提供较低层次的重新解释,本质上依赖于机器。
int *ip;
char *pc = reinterpret_cast<char*>(ip);
35、 尽量避免使用强制类型转化:强制类型转化关闭或挂起了正常的类型检查。
36、 旧式墙纸类型转化:type (exp)或者(type) exp
下面是女朋友弄的,很精美的~~