【转】effective C++ 笔记一

C 转向 C++

 

 

条款 1 :尽量使用 constinline 而不使用 #define

       #define 有很多不确定的东西, eg:

       #define max(a,b) ((a) > (b) ? (a) : (b))

       int a = 5, b = 0;

max(++a, b); // a 的值增加了 2

max(++a, b+10); // a 的值只增加了 1

 

条款2 :尽量使用<iostream> 而不用<stdio.h>

关于这点,主要是作者认为iostream 的cin,cout 都是识别类型的,不像scanf,printf 一样对不同的类型有不同的格式,然而有时候用scanf,printf 的效率要比cin,cout 的效率要高上不少。当然在重载<< 和>> 操作符号的时候,cin 和cout 表现出了强劲的强壮性。

 

条款3 :尽量使用new 和delete ,而不用malloc 和free

New 和delete 是类型识别的,而malloc 和free 始终是对void * 原汁原味的内存进行操作。而且new delete 常与类的构造和析构函数绑定到一起。

 

 

内存管理

 

 

条款4 :尽量使用C++ 风格的注释

    C 风格的注释对嵌套的注释会出问题,eg :/*/* */*/ 会出错。

 

条款5 :对应的new 和delete 要采用相同的形式

    New <=> delete

    New[]<=> delete[]

    有时候形式会比较隐蔽,eg:

    typedef string AddressLines[4];

string *pal = new AddressLines;

delete pal; // 错误

delete [] pal;// 正确

这里pal 其实是一个stirng[] ,所以delete 的时候要用delete[] ,这里主要是用了个typedef ,使得类型隐蔽了些。

 

条款6 :析构函数里对指针成员调用delete

 

条款7 :预先准备好内存不够的情况

当内存不够时,可以抛出异常之前调用客户指定的一个出错处理函数——一般称为new_handler 函数:

Typedef void (*new_handler)();

New_handler set_new_handler(new_handler p) throw();

 

条款8 :写operator new 和operator delete 时要遵循常规

    Void *operator new(size_t size);

    Void operator delete(void *rawMemory,size_t size);

 

条款9 :避免隐藏标准形式的new

    Void *operator new(size_t size,new_handler p=0);

    调用的时候,就可以用new (function) X;

 

条款10 :如果写了operator new 就要同时写operator delete

    该条款引入了内存池,值得回顾。

 

条款11 :为需要动态分配内存的类声明一个拷贝构造函数和一个赋值操作符

    该条款主要是为了防止内存的泄露和浅拷贝的发生。

 

条款12 :尽量使用初始化而不要在构造函数里赋值

    像const 和引用变量都只能用初始化;

    用初始化可以节省不必要的数据成员调用缺省的构造参数。

 

条款13 :初始化列表中成员列出的顺序和它们在类中声明的顺序相同

初始化成员的顺序,是根据它们在类中声明的顺序而定的,所以让初始化列表的顺序和在类中声明的顺序一致有较高的可读性。

 

条款 14 :确定基类有虚构函数。

使一个类成为抽象类,但又没有任何别的纯虚函数,做法是,在抽象类的类里声明一个纯虚析构函数。

Eg:

Class AWOV{

       Public:

       Virtual ~AWOV()=0;

};

AWOV::~AWOV(){}

       把虚构函数声明为内联函数并没有意义。

 

条款 15 :让 operator= 返回 *this 的引用

Eg:

// 保持赋值的连续性

//i=j=k;   (i=j)=k; 都应该是合法的。

// 不是 const string& 也不是 string

String &operator=(const char *str){

       Return *this;

}

 

条款 16:operator= 中对所有数据成员赋值

在赋值操作符的参数类型与 this 的类名一样时,要先检查 this 与参数变量的地址是否一样。

Eg:

template<class T>

NamedPtr<T>& NamedPtr<T>::operator=(const NamedPtr<T>& rhs)

{

if (this == &rhs)

return *this;

else ….

}

本条款主要针对子类在重载 = 操作符时,没有对父类的成员进行赋值。也要对父类的成员进行赋值,具体例子如下:

Derived& Derived::operator=(const Derived& rhs)

{

if (this == &rhs) return *this;

static_cast<Base&>(*this) = rhs; // *this Base 部分

// 调用 operator=

y = rhs.y;

return *this;

}

 

条款17: 在operator= 中检查给自己赋值的情况

要记得检查当进行赋值是自己给自己赋值的情况,为避免无谓的赋值操作浪费时间,而且也为了保证正确性(因为赋值操作常伴随着删除左值原来指向的内存,当自己赋值给自己发生时,就很可能出错)

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值