您的位置:首页 > 编程语言 > C语言/C++

C++ Primer 学习笔记与思考_9 表达式中过的那些容易忽略的地方

2015-08-27 21:33 579 查看
(一)移位操作符用于IO

输入输出标准库分别重载了位操作符>>和<<用于输入和输出。并且像其他的二元操作符一样,移位操作符也是左结合的,这也正好说明了我们为什么可以把多个输入输出操作连接为单个语句:

cout<<"hi"<<"there "<<endl;

将其执行为:

( (cout<<"hi")<<"there" )<<endl;

在这个语句中个,操作数”hi”和第一个<<符号结合,其计算结果和第二个<<符号结合,第二个<<操作后,去结果再和第三个<<结合。

移位操作符具有中等优先级:其优先级比算术操作符低,但是比关系运算符、赋值运算符和条件操作符优先级高。若IP表达式的操作数包含了比IO操作符优先级低的操作符,相关的优先级将影响书写该表达式的方式。这种情况下,使用圆括号强制实现右集结合。

cout<<423+10; //ok.+has higher prcedence
  cout<<10<42;// error .attempt to compare cout to 42
  cout<<(10<42) //yes
  //第二个cout解释为(cout<<10)<42,cout的结果和42比较


(二)复合赋值操作符

我们常常在对某个对象做某种操作后,再将操作结果重新赋给该对象,c++将这种用法称为复合赋值操作符

sum+=10; sum=sum+10;

这两种语法有一个显著的差别,使用复合赋值操作符时,左操作数只计算了一次;而使用相似的常表达式时,该操作数则计算了两次,第一次作为右操作数,而第二次则用作左操作数,当然这个差别不是本质性的。

(三)自增和自减操作符的一些技巧

关于i++和++i的区别我在这里就不赘述了,这里有一个很重要的建议是:只有在必要时才使用后置操作符。原因是:前置操作符所做的工作最少,只需+1后返回+1后的结果即可。而后置操作符则必须先保存操作数原来的值,以便返回+1之前的值作为操作的结果,对于int型对象和指针,编译器可优化掉这项额外的工作。但是对于更多的复杂迭代器的类型,这种额外工作可能会花费更大的代价。因此,养成使用前置操作是个好习惯,就不必操心性能差异的问题。

(四)sizeof操作符

sizeof操作符的作用是返回一个对象或者类型名的长度,也可用于求数组等在内存中的存储长度。

#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
   int sum;
   cout<<sizeof(sum)<<endl;  //4
   cout<<sizeof(int)<<endl; //4
   int x[10];
   int *p=x;
   cout<<sizeof(x)/sizeof(*x)<<endl; //10
   cout<<sizeof(p)/sizeof(*p)<<endl; //1
   
}


在表达式sizeof(x)中,x是数组名,该表达式的结果是数组x所占据的存储空间的字节数,为10个int型元素所占据的字节数;表达式sizeof(*x)的结果是指针常量x所指向的对象(数组中第一个int型元素)所占据的存储空间的字节数;表达式sizeof(p)结果是指针变量p所占据的存储空间的字节数,表达式sizeof(*p)的结果是指针变量p所指向的对象(一个int型数据)所占据的存储空间的字节数。

(五)求值顺序

如果你写出以下的比较式:

if(ia[index++]<ia[index])

我们希望先求左操作数的值,因此index+1先执行,然而,c++语言不能确保从左到右的计算次序。事实上这类表达式的行为没有明确定义,我们并不知道哪一边的表达式先执行。

除了逻辑与和逻辑或之外,C++没有明确定义二元操作符的求解次序,编译器可以自由的提供最佳奖的实现方式。

(六)new和delete表达式

1.new

前几篇博客已经讲过了关于new和delete的基本操作,这里在叙述一些细节。

int pi1=new int; //未初始化 
   int pi2=new int();//0
   string *pos1=new string;
   string *pos2=new string(); 
    int *ip=0;
   delete ip; //delete NULL is ok


动态创建的对象和在函数内部创建的变量的初始化方式相同,对于类类型的对象,用该类的默认构造函数初始化;而内置类型的对象则无初始化。

()代表初始化,内容为空表示未提供特定的初值,string不用()初始化,因为会自动调用类的构造函数。

2.const对象的动态分配和回收

const int *pci=new const int(1024);

delete pci;

动态创建的const对象必须在创建时初始化,因为是const对象,所以指针智能赋给指向const的指针。delete时和其他动态对象一致。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: