1. 定义变量会引发构造和析构开销 每当你定义一种类型的变量时:当控制流到达变量的定义点时,你引入了调用构造函数的开销,当离开变量的作用域之后,你引入了调用析构函数的开销.对未使用到的变量同样会产生开销,因此对这种定义要尽可能的避免. 2. 普通函数中的变量定义推迟 2.1 变量有可能不会被使用到的例子 你可能会想你永远不会定义未使用的变量,你可能要再考虑考虑.看下面的函数,此函数返回password的加密版本,提供的password需要足够长.如果password太短,函数会抛出一个logic…
C++设计的规则是用来保证使类型相关的错误不再可能出现.理论上来说,如果你的程序能够很干净的通过编译,它就不会尝试在任何对象上执行任何不安全或无意义的操作.这个保证很有价值,不要轻易放弃它. 不幸的是,casts颠覆了类型系统.它导致了各种麻烦的出现,一些很容易识别,一些却很狡猾(不容易被识别).如果你以前使用过C,java或者C#,你就需要注意了,因为在这些语言中casting是更加必不可少的,但却比C++更安全.C++不是C,不是java也不是C#,在C++中,你需要怀着极大的敬意来使用ca…
这个条目叫做,尽量使用编译器而不要使用预处理器更好.#define并没有当作语言本身的一部分. 例如下面的例子: #define ASPECT_RATIO 1.653 符号名称永远不会被编译器看到.它可能在源码到达编译器之前被预处理器移除.ASPECT_RATIO 最终不会进入符号表,如果因为这个常量的使用而导致编译错误,会使你非常迷惑,因为错误信息会指向1.653而不是ASPECT_RATIO.如果ASPECT_RATIO被定义在一个不是你自己写的头文件中,你会不知道1.,653来自哪里.,…
1. 什么样的接口才是好的接口 C++中充斥着接口:函数接口,类接口,模板接口.每个接口都是客户同你的代码进行交互的一种方法.假设你正在面对的是一些“讲道理”的人员,这些客户尝试把工作做好,他们希望能够正确使用你的接口.在这种情况下,如果接口被误用,你的接口应该至少负一部分的责任.理想情况下,如果使用一个接口没有做到客户希望做到的,代码应该不能通过编译:如果代码通过了编译,那么它就能做到客户想要的. 2. 编写好的接口的方法列举 2.1 使接口不容易被误用——通过引入新的类型 开发出容易被正确使…
1. 将需要隐式类型转换的函数声明为成员函数会出现问题 使类支持隐式转换是一个坏的想法.当然也有例外的情况,最常见的一个例子就是数值类型.举个例子,如果你设计一个表示有理数的类,允许从整型到有理数的隐式转换应该是合理的.在C++内建类型中,从int转换到double也是再合理不过的了(比从double转换到int更加合理).看下面的例子: class Rational { public: Rational(, // ctor is deliberately not explicit; ); //…
1. new-handler介绍 当操作符new不能满足内存分配请求的时候,它就会抛出异常.很久之前,它会返回一个null指针,一些旧的编译器仍然会这么做.你仍然会看到这种旧行为,但是我会把关于它的讨论推迟到本条款结束的时候. 1.1 调用set_new_handler来指定全局new-handler 在operator new由于不能满足内存分配要求而抛出异常之前,它会调用一个客户指定的叫做new-handler的错误处理函数.(这也不是完全正确的.Operator new的真正行为更加复杂.…
1. C++0x的历史渊源 C++标准——也就是定义语言的文档和程序库——在1998被批准.在2003年,一个小的“修复bug”版本被发布.然而标准委员会仍然在继续他们的工作,一个“2.0版本”的C++标准预计在2009年被发布(虽然所有的工作很有可能在2007年底被完成).直到现在,发布下一版C++的预计年份还没有被确定,这就解释了为什么人们把下一版C++叫做“C++0x”——C++的200x年版本. C++0x可能会包含一些有趣的新的语言特性,但是大多数新C++功能将会以标准库附加物的形式被…
Item 1 将c++视为一个语言联邦 如今的c++已经是一个多重泛型变成语言.支持过程化,面向对象,函数式,泛型和元编程的组合.这种强大使得c++无可匹敌,却也带来了一些问题.所有“合适的”规则看上去都有例外.我们怎样理解这样一门语言? 最容易的方法是不要将其看成单一的一门语言而是将其看成是一个有相关性的语言的联邦.在一个特定的子语言中,一些规则就比较简单,明确并且容易记忆.当你从一个子语言切换到另外一个子语言时,这些规则可能会改变.为了更好的理解c++,你必须识别主要的子语言,幸运的是,只有…
关于构造函数的一个违反直觉的行为 我会以重复标题开始:你不应该在构造或者析构的过程中调用虚函数,因为这些调用的结果会和你想的不一样.如果你同时是一个java或者c#程序员,那么请着重注意这个条款,因为这是c++同它们不一样的地方. 假设你已经有一个为股票交易建模的类继承体系,它可以买卖股票等.这些交易的可审计性很重要,所以每次交易对象被创建的时候,需要在审计日志中创建一个合适的记录.这看上去是解决问题的合理方法: class Transaction { // base class for all…
1.自我赋值是如何发生的 当一个对象委派给自己的时候,自我赋值就会发生: class Widget { ... }; Widget w; ... w = w; // assignment to self. 这看上去是愚蠢的,但这是合法的,所以请放心,客户端是可以这么做的.此外,自身赋值也并不总是很容易的能够被辨别出来.举个例子: a[i] = a[j]; // potential assignment to self 上面的代码在i和j相等的情况下就是自我赋值,同样的,看下面的例子: *px =…