More Effective C++:Item 1-Item 8读书笔记

Item M1: 指针与引用的区别

在以下情况下你应该使用指针,一是你考虑到存在不指向任何对象的可能(在这种情况下,你能够设置指针为空),二是你需要能够在不同的时刻指向不同的对象(在这种情况下,你能改变指针的指向

Item M2:尽量使用C++风格的类型转换

static_cast在功能上基本上与C风格的类型转换一样强大,含义也一样;
const_cast用于类型转换掉表达式的const或volatileness属性;
dynamic_cast,它被用于安全地沿着类的继承关系向下进行类型转换;
reinterpret_cast。使用这个操作符的类型转换,其的转换结果几乎都是执行期定义(implementation-defined)。因此,使用reinterpret_casts的代码很难移植,转换函数指针的代码是不可移植的(C++不保证所有的函数指针都被用一样的方法表示).

Item M3:不要对数组使用多态

如果你不从一个具体类(concrete classes)(例如BST)派生出另一个具体类(例如BalancedBST),那么你就不太可能犯这种使用多态性数组的错误。

Item M4:避免无用的缺省构造函数

在一个完美的世界里,无需任何数据即可建立对象的类可以包含缺省构造函数,而需要数据来建立对象的类则不能包含缺省构造函数。唉!可是我们的现实世界不是完美的,所以我们必须考虑更多的因素。特别是如果一个类没有缺省构造函数,就会存在一些使用上的限制。

1.第一种情况是建立数组时。一般来说,没有一种办法能在建立对象数组时给构造函数传递参数。
2.对于类里没有定义缺省构造函数所造成的第二个问题是它们无法在许多基于模板(template-based)的容器类里使用。因为实例化一个模板时,模板的类型参数应该提供一个缺省构造函数,这是一个常见的要求。

Item M5:谨慎定义类型转换函数

有两种函数允许编译器进行这些的转换(类C的转换):单参数构造函数(single-argument constructors)和隐式类型转换运算符。

解决方法:
1.explicit关键字;
2.Proxy对象能帮你更好地控制软件的在某些方面的行为,否则你就不能控制这些行为

Item M6:自增(increment)、自减(decrement)操作符前缀形式与后缀形式的区别

// 前缀形式:增加然后取回值
UPInt& UPInt::operator++()
{
*this += 1; // 增加
return *this; // 取回值
}
// postfix form: fetch and increment
const UPInt UPInt::operator++(int) //int 忽略,避免编译器警告
{
UPInt oldValue = *this; // 取回值
++(*this); // 增加
return oldValue; // 返回被取回的值
}

如果你很关心效率问题,当你第一次看到后缀increment函数时,你可能觉得有些问题。这个函数必须建立一个临时对象以做为它的返回值,(参见条款M19),上述实现代码建立了一个显示的临时对象(oldValue),这个临时对象必须被构造并在最后被析构。前缀increment函数没有这样的临时对象。由此得出一个令人惊讶的结论,如果仅为了提高代码效率,UPInt的调用者应该尽量使用前缀increment,少用后缀increment,除非确实需要使用后缀increment。让我们明确一下,当处理用户定义的类型时,尽可能地使用前缀increment,因为它的效率较高。

ItemM7:不要重载“&&”,“||”, 或“,”

不能被重载的运算符:
.
.*
::
?:
new delete sizeof typeid
static_cast ;dynamic_cast;const_cast;reinterpret_cast

C++允许根据用户定义的类型,来定制&&和||操作符。方法是重载函数operator&& 和operator||,你能在全局重载或每个类里重载。然而如果你想使用这种方法,你必须知道你正在极大地改变游戏规则。因为你以函数调用法替代了短路求值法

Item M8:理解各种不同含义的new和delete

new
你使用的new是new操作符。这个操作符就象sizeof一样是语言内置的,你不能改变它的含义,它的功能总是一样的。它要完成的功能分成两部分。第一部分是分配足够的内存以便容纳所需类型的对象。第二部分是它调用构造函数初始化内存中的对象。new操作符总是做这两件事情,你不能以任何方式改变它的行为。

你所能改变的是如何为对象分配内存。new操作符调用一个函数来完成必需的内存分配,你能够重写或重载这个函数来改变它的行为。new操作符为分配内存所调用函数的名字是operator new。
operator new
就象malloc一样,operator new的职责只是分配内存。它对构造函数一无所知。
placement new
有时你确实想直接调用构造函数。在一个已存在的对象上调用构造函数是没有意义的,因为构造函数用来初始化对象,而一个对象仅仅能在给它初值时被初始化一次。但是有时你有一些已经被分配但是尚未处理的(raw)内存,你需要在这些内存中构造一个对象。你可以使用一个特殊的operator new ,它被称为placement new。

operator new的目的是为对象分配内存然后返回指向该内存的指针.
总结
让我们从placement new回来片刻,看看new操作符(new operator)与operator new的关系,你想在堆上建立一个对象,应该用new操作符。它既分配内存又为对象调用构造函数。如果你仅仅想分配内存,就应该调用operator new函数;它不会调用构造函数。如果你想定制自己的在堆对象被建立时的内存分配过程,你应该写你自己的operator new函数,然后使用new操作符,new操作符会调用你定制的operator new。如果你想在一块已经获得指针的内存里建立一个对象,应该用placement new。

new和delete操作符是内置的,其行为不受你的控制,凡是它们调用的内存分配和释放函数则可以控制。当你想定制new和delete操作符的行为时,请记住你不能真的做到这一点。你只能改变它们为完成它们的功能所采取的方法,而它们所完成的功能则被语言固定下来,不能改变

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tingzhushaohua

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值