读Defective C++随笔 3

读Defective C++随笔 3

不尽知用兵之害者,则不能尽知用兵之利也 ——《孙子兵法》


5.const完备问题
对C来说,const看起来是很合理的,将参数声明成const的,可以利用编译器的语法检查避免一些不期望的修改错误,而且可能帮助编译器做一些优化。多数官方文献都强烈要求程序员编写const完备的C++代码,极力避免const_cast,但现实中大部分代码只能是基本使用了const。问题在于,一但涉及到类,const就会引出很多的问题。

有C++经验的人应该都体会过,任何使用了const的代码都将迫使任何接触它的代码支持const,同时任何不使用const的代码都迫使任何接触它的代码不使用const。所以我们对如下代码习以为常:
const Foo& GetFoo() const;
Foo& GetFoo();

这对类方法函数被称作const重载。为了同一类型在const和非const时都能用,我们不得不把很多方法写两遍,而且必须是完全重写,因为它们中任何一个都不能调用另外一个,除非你使用被说成邪恶的const_cast,还有传说中更邪恶的C风格强制转换。然后Foo的方法也必须支持const重载,以此类推。

不过简单的属性访问函数一般都不长,但如果不是简单的访问呢?比如如果需要缓存最近访问的数据以提高效率,这时必须修改一些内部成员,但它又必须可以在const对象调用。于是C++里有了mutable关键字,用来指定一些成员可以被const方法修改。

另外,对于函数参数,同样的问题也存在,而且有时非常不可思议。比如vector类型的变量不能传给const vector&类型的参数,当然,const vector&和vector&类型的参数更不能。那应该怎么做?如果你想到了,那恭喜你,你C++及格了。原则上正确的做法是传递iterator而不是集合对象的引用。所以才有T::const_iterator和T::iterator两个类。等等,为什么需要两个类而不是一个iterator类加const关键字?因为iterator需要做自加或自减,加const关键字就改不了了,所以只能再写一遍。那下一个问题,如果不是传参数,而是要把vector的变量赋给const vector&的变量怎么办?欢迎作答。

很明显,必须把同样的事情做两遍有违“重用”的目标,但C++选择了安全性。如果我们使用了const_cast,那是我们程序员的责任,是因为我们没有做出完美的设计。

const在C++里的另一个副作用是,加const的类型和不加const的类型是不同的类型,所以vector和vector是不同的类型,所以编译器生成两份完全一样的代码。所以,我们都知道用了STL编译出的程序就会很大。

你可能感兴趣的:(编程语言)