C++ primer笔记——第五章 表达式

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

下面是女朋友弄的,很精美的~~


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值