学习程序设计语言是一回事,学习如何以某种语言设计并实现高效程序则是另一回事。


《Effective C++》使你的软件易理解、易维护、可移植、可扩充、高效、并且有着你所期望的行为。


作者的建议分为两类:1)一般性的设计策略;2)带有具体细节的特定语言特性。


本书是一份55个特定建议的集合,谈论如何强化你的程序和设计。每个条款有相当程度的独立性,但大多数也参考其他条款。


本书目的是要强调那些常被漠视的C++编程方向和观点。其他书籍描述C++语言的各个成分,本书告诉你如何结合那些成分以便最终获得有效程序。其他书籍告诉你如何让程序通过编译,本书告诉你如何回避编译器难以显露的问题。


本书最佳用途是彻底了解C++如何行为、为什么那样行为、以及如何运用其行为形成优势。



声明declaration:告诉编译器某个东西的名称和类型,但略去细节。

eg: std::size_t numDigits(int numbers);//函数function的声明式子,函数numDigit的返回类型是std::size_t,这表示size_t位于命名空间std内。size_t只是一个typedef,是

(每个函数的声明揭示其签名式signature,也就是参数和返回类型。一个函数的签名等同于该函数的类型。)


定义definition:提供编译器一些声明式所遗漏的细节。对对象而言,定义式是编译器为此对象拨发内存的地点。对function 或function template而言,定义式提供了代码本体。对class 或 class template而言,定义式列出它们的成员。


初始化Initialization 是“给予对象初值”的过程。对用户自定义类型的对象而言,初始化由构造函数执行。所谓default构造函数是一个可被调用而不带任何实参者。这样的构造函数要不没有参数,要不就是每个参数都有缺省值。

class A{
	public:
		A();//default构造函数 
};

class B{
	public:
		explicit B(int x=0,bool b=true);// default构造函数 
}; 

class C{
	public:
		explicit C(int x); //不是 default构造函数 
};



上述的class B和C的构造函数都被声明为

explicit,这可阻止它们被用来执行隐式类型转换(implicit type conversions),但它们仍可被用来进行显示类型转换(explicit type conversions)。

void doSomething(B object);//函数,接受一个类型为B的对象 

B bObj1;//一个类型为B的对象 
doSomething (bObj1);//没问题,传递一个B给doSomething函数 
B bObj2(28);//没问题,根据int 28建立一个B,(函数的bool参数缺省为true) 

doSomething(28);//错误!doSomething应该接受一个B,不是一个int,而int至B之间并没有隐式转换。 

doSomething( B(28));//没问题,使用B构造函数将int显示转换(转型,cast)为一个B以促成此一调用。




被声明为explicit的构造函数通常比其non-explici更受欢迎,因为它们禁止编译器执行非预期(往往也不被期望)的类型转换。除非有一个好利用允许构造函数被用于隐式类型转换,否则我会把它声明为explicit。


copy构造函数被用来“以同型对象初始化自我对象”,copy assignment操作符被用来“从另一个同型对象中拷贝其值到自我对象”。

class Widget{
	public:
		Widget();	//default构造函数 
		Widget(const Widget& rhs);	//copy构造函数 
		Widget& operator=(const Widget& rhs);	//copy assignment操作符 
}; 
Widget w1;	//调用default构造函数 
Widget w2(w1);//调用copy构造函数 
w1 = w2;	//调用copy assignment操作符



当看到赋值符号时小心,因为“=”语法也可用来调用copy构造函数:

Widget w3=w2; //调用copy构造函数


“copy构造” VS “copy赋值”: 如果一个新对象被定义(如以上语句中的w3),一定会有个构造函数被调用,不可能调用赋值操作。如果没有新对象被定义(如前面的“w1=w2”语句),就不会有构造函数被调用,那么当然就是赋值操作被调用。


copy构造函数是一个重要函数,因为它定义了一个对象如何passed by value(以值传递)。


STL是所谓标准模板库(Standard Template Library),是C++标准程序库的一部分,致力于容器(vector, list, set, map等等)、迭代器(如 vector<int>::iterator, set<string>::iterator等等)、算法(for_each,find,sort等等)及相关机能。许多相关机能以函数对象 function object是实现,那是“行为像函数”的对象。这样的对象来自于重载operator() (function call操作符)的classes。


不明确行为undefined behavior

由于各种因素,某些C++构件的行为没有定义 :你无法稳定预估运行期间会发生什么事。

int *p=0;//p是一个null指针 
std::cout<<*p;//对一个null指针取值(dereferencing)会导致不明确行为 

char name[]="Darla";//name是一个数组,大小是6,不能忘记末尾的null 
char c= name[10]; //指向一个无效的数组索引,导致不明确的行为


接口 interface

Java和 .NET语言提供Interfaces为语言元素,但C++没有。作者使用术语“接口”时,一般谈的是函数的签名signature 或 class的可访问元素(例如class的 “public接口” 或 “protected接口” 或 “private接口”),或是针对某template类型参数需为有效的一个表达式。


客户client:指某人或某物,他(或它)使用你写的代码(通常是一些接口)。函数的客户是指其使用者,也就是程序中调用函数(或取其地址)的那一部分,也可以说是编写并维护那些代码的人。class 或 template的客户则是指程序中使用class或template的那一部分,也可以说是编写并维护那些代码的人。




命名习惯


关于线程 Threading Consideration

作为一个语言,C++对线程threads没有任何意念-事实上它对任何并发concurrency事物都没有意念。C++标准程序库也一样。

线程安全性 thread safety是许多程序员面对的主题。作者对所检验的C++构件在多线程环境中有可能引发问题,就把它指出来。


TR1和Boost

TR1是一份规范,描述加入C++标准程序库的诸多新机能。这些机能以新的class templates 和 function templates形式体现,针对的题目有 hash tables,reference-counting,smart pointers,regular expressions,以及更多。所有TR1组件都被置于命名空间tr1内,后者嵌套于命名空间std内。


Boost是个组织,亦是一个网站,提供可移植、同僚复审、源码开放的C++程序库。大多数TR1机能是以Boost的工作为基础。Boost提供比TR1更多的东西,所以无论如何值得了解。


《Effective C++》第三版 侯捷译  vii ~10