您的位置:首页 > 编程语言 > C语言/C++

Effective C++读书笔记版-条款03、04

2015-09-10 09:41 411 查看
条款03:尽可能使用const

尽可能使用const可能会让你多写很多个const,而且会在你试图改变被const修饰的“变量”时报告一大堆bugs。然而,如果没有了它们,就成了掩耳盗铃了吧?后果是不是不堪设想呢?很简单,你只需要看看const修饰的是谁,就知道谁不能被改变了。

对于返回const的函数,它是为了防止你或者别人对返回的对象进行写操作(赋值)。

bitwise const成员函数保证了在函数内部任何成员(static除外)都不会被改变,logical const则会给需要改变的成员变量在声明时加上mutable关键字。

第二版条款03:尽量用new和delete而不用malloc和free

在C中,我们谨记malloc和free是我们在使用指针时的忠实朋友,在C++中,我们需要为对象、为含有对象的对象进行内存分配的时候,malloc和free就帮不了我们太多了,因为它们不知道还有构造和析构这样的事情。

为了能够把const与non-const严格区别对待,你需要重载函数,这就意味着代码重复。或许你也想到让non-const去调用const或者反过来(有点危险和莫名其妙,我们不是为了const而来的吗?)。

class TextBlock { public: ... const char& operator[](std::size_t position) const // same as before

{ ... // do bounds checking

... // log access data

... // verify data integrity

return text[position];

}

char& operator[](std::size_t position) // now just calls const op[]

{

return

const_cast<char&>(

// cast away const on 这儿很好理解

static_cast<const TextBlock&>(*this) // add const to *this's type; 避免递归调用自身 [position] // call const version of op[]

);

}

... };

条款04:确定对象在使用前已先被初始化

关于语言本身对初始化的保证,从C到C++一直是个讨论的热点,Scott说:“always initialize your objects before you use them”。

class PhoneNumber { ... };

class ABEntry

{ // ABEntry = "Address Book Entry"

public:

ABEntry(const std::string& name, const std::string& address,

const std::list<PhoneNumber>& phones);

private:

std::string theName;

std::string theAddress;

std::list<PhoneNumber> thePhones;

int num TimesConsulted; };

// 赋值做法,相信每一个C程序员都对这样的写法倍感亲切

ABEntry::ABEntry(const std::string& name, const std::string& address,

const std::list<PhoneNumber>& phones)

{ theName = name; // these are all assignments,

theAddress = address; // not initializations

thePhones = phones

numTimesConsulted = 0; }

// 成员初始列做法,这才是初始化

ABEntry::ABEntry(const std::string& name, const std::string& address,

const std::list<PhoneNumber>& phones) : theName(name),

theAddress(address), // these are now all initializations

thePhones(phones),

numTimesConsulted(0) // 这个built-in type无所谓,不存在效率上的问题 {}

// the ctor body is now empty

不仅仅是习惯问题,先调用default constructor再进行copy assignment显然比直接调用copy constructor要慢半拍(岂止啊)!对于const或references因为无法赋值,只能使用初始列。而且,初始化顺序也应该遵循先base后derived,FCFS的原则。

至于例外也不是没有,为了避免涉及数据读写的大量变量在赋值前多余的初始化(前提是你正确的知道那是多余的),合理改用赋值是明智的。

“The relative order of initialization of non-local static objects defined in different translation units is undefined.”对于different translation units中定义的non-local static objects们,我们不可能也没有必要在每次使用时都对其初始化,然而我们又的确需要初始化已经实施过这样的保证,GoF提出的Singleton模式、解决了这个问题。

说句实话,我很少使用non-local static objects,但是我也很少使用local static objects。虽然我对《Design Pattern》看过多遍,但你也体会到了,那又能说明什么呢?

第二版条款04:尽量使用c++风格的注释

为了强调要从C转向C++,Scott连C的注释风格也一起批判:

if ( a > b ) {

// int temp = a; // swap a and b

// a = b;

// b = temp; } ==>

if ( a > b ) {

/* int temp = a; /* swap a and b */

a = b;

b = temp; */ }

啊喔,因为注释不能嵌套,上面的修改导致了编译时无法通过。

看来,从C到C++,必须要转变的彻底才行。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: