📚
cpp
  • README.md
  • Effective c++
    • 1.让自己习惯c++
    • 2.构造/析构/赋值运算
    • 3.资源管理
    • 4.设计与声明
    • 5.实现
    • 6.继承与面向对象设计
    • 7.模板与泛型编程
    • 8.定制new和delete
  • More effective c++
    • 1.基础议题
    • 2.操作符
    • 3.异常
    • 4.效率
    • 5.技术
    • 6.杂项讨论
  • effective modern c++
    • 1.型别推导
    • 2.auto
    • 3.转向现代c++
    • 4.智能指针
    • 5.右值引用,移动语义和完美转发
    • 6.lambda表达式
    • 7.并发API
    • 8.微调
  • stl源码剖析
  • cpp-concurrency-in-action
Powered by GitBook
On this page
  • 条款01:仔细区别points和references
  • 条款02:最好使用c++转型操作符
  • 条款03:绝对不要以多态的方式处理数组
  • 条款04:非必要不提供 default construction

Was this helpful?

  1. More effective c++

1.基础议题

条款01:仔细区别points和references

指针和引用有很多相似的地方,但是用法还是有区别。所以一般还是不会搞混。

这里需要注意的是,points是可以为null的但是reference必须得有初始时。这可能也意味着很多时候,使用引用效率会高于使用指针。因为使用一个指针之前,一定要判断它是否被初始化。

直接对一个引用取地址,得到的是和被引用数一样的地址。利用gdb反汇编,分析引用值存储的栈空间地址,查看其值,可以知道,引用本质上就是用指针实现的。使用的是const point。

条款02:最好使用c++转型操作符

这个条款在effective c++中已经提过了,c++提供了4种新式转型:

  • static_cast<>:类似于之前的C转型动作

  • const_cast<>:去除const和volitileness

  • dynamic_cast<>:将base class转化为drived class的转型

  • reinterpret_cast<>:这个转型我也不是很懂,例子里是可以将point转为int

结论就是:c++转型操作又臭又长,很不好使用。但是提供严谨意义与易辨识度。并且让转型操作又臭又长,未必不是一件好事。

条款03:绝对不要以多态的方式处理数组

对于多态不是很陌生,但是看到这个条款的时候,还是没有马上想到相应的情况。

如果只用base指针指向drived对象,这是肯定没问题的。如果析构函数定义为virtual的,delete base也是正确。但是如果定义一个base数组,数组中每个指针都指向drived对象。在delete []数组的时候,就会出问题。

这里首先会调用所有对象的析构函数,然后释放空间。这是c++中的未定义行为,base指针删除一个由drived classes object定义的数组。

然后还有一种情况也会出问题。这里需要知道的核心部分还是:多态是动态绑定,但是函数参数是静态绑定。在编译期,编译器就会为静态绑定设计好代码。如果一个函数的参数是base数组,但是传入了一个drived 数组,就可能会出问题。

如下代码,每次i+1,array地址会加sizeof(base),而不是sizeof(drived),这就会出问题

void printBSTarray(ostream&s,const BST array[],int numElement){
    for(int i=0;i<numElement;++i){
        s<<array[i];
    }
}

条款04:非必要不提供 default construction

这个条款首先说没必要的时候,不提供默认构造函数。但是马上却列出了不提供默认构造函数会出现的很多问题。所以这个条款看起来有点矛盾

  • 首先问题是如果没有默认构造函数,无法直接调用new []构造对象数组。处理方法是先构造对象指针数组,然后再单个调用构造函数。或者是用placement new

  • 还有一个问题就是,如果基类没有默认构造函数。派生类构造的时候,就必须调用基类带参数的构造函数。如果继承比较复杂,这将很痛苦

  • 最后结论是,如果默认构造函数能够提供对象的所有字段都被完整初始化的确保,那么提供一个默认构造函数是可以的。否则,不要提供一个默认构造函数

PreviousMore effective c++Next2.操作符

Last updated 5 years ago

Was this helpful?