大二寒假读书笔记150205

来源:互联网 发布:网络舆情监控方案 编辑:程序博客网 时间:2024/04/26 09:24

1、sizeof操作符的作用是返回一个对象或类型名的长度,长度的单位是字节,返回值类型是size_t。sizeof表达式的结果是编译时常量,有以下三种语法:

sizeof(type name);sizeof(expr);sizeof expr;

将sizeof应用在表达式expr上,将获得该表达式的结果的长度

Sales_item item , *p;sizeof item;sizeof *p;

将sizeof用于expr时,并没有计算表达式expr的值。特别是在sizeof *p中,指针p可以指向一个无效地址,因为不需要对p做解引用操作。
使用sizeof的结果部分地依赖所涉及的类型:
*对char类型或值为插入类型的表达式保证得1
*对引用类型将返回存放此引用类型对象所需的内存空间大小
*对指针将返回指针所需的内存大小;注意,如果要获得该指针所指对象的大小,则必须进行解引用。
*对数组等效于对其元素类型的结果乘以数组元素的个数。
因为sizeof返回整个数组在内存中的存储长度,所以:

int sz = sizeof(ia)/sizeof(*ia);

2、结合性
结合性规定了具有相同优先级的操组符如何分组。
赋值操作具有右结合性

ival = jval = kval = lval;(ival = (jval = (kval = lval)));

算术操作为左结合性

ival * jval / kval * lval;(((ival * jval) / kval) * lval)

然后操作符的优先级,点这里

3、求值顺序
我们曾讨论过&&和||操作符计算其操作数的次序:当且仅当其左操作数无法确定整个表达式的值的时候,才计算这两个操作符的右操作数。

while(iter != iter.end() && * iter != some_val)

C++中,规定了操作数计算顺序的操作符还有条件(?:)和逗号操作符。除此之外,其他操作符并未指定其操作数的求值顺序。
但是!如果一个子表达式修改了另一个子表达式的操作数,则操作数的求解次序就变得相当重要:

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

此表达式的行为没有明确定义。假设index的初值为0,则编译器可以用下面两种方式之一求该表达式的值:

if (ia[0] < ia[1])//先计算左值if (ia[0] < ia[0])//先计算右值

可以假设程序猿希望先求左操作数的值,然而这样的话,C++不能确保从左到右的计算次序。事实上,这类表达式的行为没有明确定义。
为了防止误解表达式和操作符求解顺序,我们有两个指导原则:
*使用圆括号去强制操作数的组合
*如果要修改操作数的值,则不要在同一个语句的其他地方使用该操作数。就是说,一个表达式里,不要在两个或更多子表达式中对同一对象做自增或自减操作。
4、new和delete表达式ichule动态创建和释放数组,也可以用来动态创建和释放单个对象:

int i;int *pi = new int;

这个new表达式在自由存储区中分配创建了一个整型对象,并返回此对象的地址,同时用改地址初始化指针pi。
C++使用直接初始化语法规则初始化动态创建的对象:

int i(1024);int *pi = new int(1024);string s(10,'a');string *ps = new string(10,'a');

如果不提供显式初始化,动态创建的对象与在函数内定义的变量初始化方式相同。对于类类型的对象,用该类的默认构造函数初始化;而内置类型的对象则无初始化。
同样可以对动态创建的对象做值初始化,对于提供了默认构造函数的类类型没必要对其进行值初始化,对于内置类型,采用不同的初始化方式有区别:

int *pi = new int;//uninitializedint *pi = new int();//0

5、如果总是new不释放内存,用完所有内存之后,将会抛出bad_alloc的异常。
动态创建的对象用完后,程序猿必须显式地将该对象占用的内存返回给自由存储区。

int *pi = new int();cout<<*pi<<endl;delete pi;

如果指针指向的不是用new分配的内存地址,则在该地址上使用delete是非法的!可是编译器一般检查不出来。

    int i;    int *pi = &i; // string str = "hello";    double *pd = new double(33);//   delete str;     delete pi;     delete pd; 

编译器会拒绝str的delete语句,但是编译器不能断定一个指针指向一个什么类型的对象,所以delete pi;这条语句通过了编译。
另外C++保证删除0指指针是安全的。不过没有任何意义。

int *pi = 0;delete pi;

6、在delete之后,重设指针的值
执行语句

delete p;

后,p没有定义。在很多机器上,尽管p没有定义,但仍然存放了它之前所指向对象的地址。删除指针后,该指针变成悬垂指针。它仍然指向曾经存放对象的地址,但该对象已经不存在了,因此往往导致错误,并且很难检测出来。soo,一旦删除了指针所指向的对象,立即将指针置为0,这样就很清楚地表明指针不指向任何对象。
7、const对象的动态分配和回收

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

上述的new表达式返回的是一个指针,指向int型const对象。
对于类类型的const动态对象,如果该类提供了默认构造函数,则此对象可以隐式初始化:

const string *pcs = new const string;

内置类型或为提供默认构造函数的类类型必须显式初始化!
尽管程序猿不能修改const对象的值,但可撤销对象本身:

delete pcs;

8、有点牵涉内存知识。
介绍三种常见的程序错误,都与动态内存分配相关:
*删除指向动态分配内存的指针失败,因而无法将该块内存返还给自由存储区。删除动态分配内存失败称为“内存泄漏”,除非等到程序使用一段时间耗尽了所有内存空间,否则很难发现。
*读写已删除的对象。所以要删除指针所指的对象之后,将指针置为0值。
*对同一块内存空间使用两次delete表达式。使用第二次delete表达式可能会破坏此自由存储区。

0 0