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

条款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++,必须要转变的彻底才行。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值