现在的位置: 首页 > 综合 > 正文

读书笔记-Thinking in C++-第6章 初始化和清除Initialization& Cleanup

2013年10月01日 ⁄ 综合 ⁄ 共 1894字 ⁄ 字号 评论关闭
 

C中的大量错误是由于没有正确的初始化或者清除造成的,通常C库是不提供初始化的,这时用户必须手动的初始化struct
 
用constructor构造函数确保初始化
在C++中,初始化太重要了以至于不能留给用户来做(too important to leave to the client programmer.)类的设计者提供了一种特殊函数constructor来确保对每一个对象进行初始化,当创建对象的时候,编译器自动调用构造函数。
 
问题在于如何定义构造函数,首先确保构造函数名字不与其他变量或者函数名冲突,其次编译器要知道调用谁,因此构造函数的名字和类class名相同。
 
当程序到达变量定义的地方时,编译器将自动调用构造函数,传递给构造函数的第一个隐藏参数时this指针。This指针指向一块未初始化的内存,有构造函数来进行初始化。
 
在C++中定义和初始化是紧密联系在一起的概念。构造函数和析构函数是特殊的函数,他们都没有返回值,这和返回void类型的概念是不一样的。因为若有返回值并且你可以任意选择,那么编译器将不知道如何处理这些返回值。
 
析构函数确保清除cleanup
析构函数的名字同类名,只是前面加了~标志,表示相反的概念。其没有参数和返回值。
 
编译器将在对象的有效范围结束时自动调用析构函数(destructor is automatically called at the closing brace of the scope that encloses it.)。标志点是“}”即closing brace,即使用goto跳出这个范围,析构也将自动执行。
 
清除定义块
在C中,必须在“{”之后即块的开始定义变量,通常的理由是这是良好的编程习惯,但在将使用某变量时再定义将提高可读性。
 
在C中,没有private的概念,定义和初始化可以分开,可以在任何时候对其进行初始化。但C++要求定义的时候必须初始化,这样可以确保系统中没有未初始化的对象。当构造函数具备多个初始化参数时,而在“{”之后还未完全具备时,将不能定义该对象。因此在C++中,可以在“{}”之内任意位置随便定义对象或者built-in变量,这样可以保证定义和初始化同时进行。
 
在C++中,通常你应该在需要使用某变量时再定义之,并且定义的时候对其初始化,这样缩小了其有效范围,减少了误用的概率;另外提高了可读性,读者不用jump back and forth到变量定义的地方。
 
对于循环loops
for(int j = 0; j < 100; j++)
{ cout << "j = " << j << endl; }
在C++中,可以在for循环中定义变量,而在C中却不能。并且J的作用范围只在『』之内,不必特意用别的名字来定义J
 
内存分配
尽管在C++中可以在任何位置定义对象,但仍然采用C中的规定,在“{”之后为所有对象分配内存,但构造函数直到对象定义处才执行,并且编译器会确保你不会把对象定义放在只有某种条件才到达的代码中,如switch或者goto
 
void f(int i) {
if(i < 10) {
//! goto jump1; // Error: goto bypasses init
}
X x1;
// Constructor called here
jump1:
switch(i) {
case 1 :
X x2; // Constructor called here
break;
//! case 2 : // Error: case bypasses init
X x3; // Constructor called here
break;
}
}
 
集合初始化
在C++中集合的初始化将变得更安全,特别是只有部分初始化值时,如
int b[6] = {0};
编译器将对第一个赋值0,其余的默认为0,而不是未初始化,其在编译阶段完成,不需要在运行阶段对其进行loop循环赋值
 
另外一个好处是自动计算集合的长度
int c[] = { 1, 2, 3, 4 };
当对其进行更改时只需要加上对应的初始化值即可,而不需更改其长度,减少了出错的可能性
for(int i = 0; i < sizeof c / sizeof *c; i++)
c[i]++;
采用sizeof c / sizeof *c方式来计算数组长度,在任何时候都是正确的,具备很好的自适应性
 
struct X {
int i;
float f;
char c;
};
X x1 = { 1, 2.2, 'c' };
因为struct成员默认为public的,因此可以直接对其赋值
X x2[3] = { {1, 1.1, 'a'}, {2, 2.2, 'b'} };
第三个默认为0
 
当对象含有构造函数时,必须显示的调用构造函数
struct Y {
float f;
int i;
Y(int a);
};
Y y1[] = { Y(1), Y(2), Y(3) };

 

抱歉!评论已关闭.