学习程序设计语言是一回事,学习如何以某种语言设计并实现高效程序则是另一回事。
《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