1ms Faster
Home
  • Program

    • Lean in C++
  • Perfromance Engineering

    • [>>>>>]
  • Reading Note

    • [>>>>>]
  • ComputeArch

    • [_]
  • Compiler

    • [_]
  • System

    • [_]
Authoring
  • Categories
  • Tags
GitHub (opens new window)

Quincy Jet

We are.
Home
  • Program

    • Lean in C++
  • Perfromance Engineering

    • [>>>>>]
  • Reading Note

    • [>>>>>]
  • ComputeArch

    • [_]
  • Compiler

    • [_]
  • System

    • [_]
Authoring
  • Categories
  • Tags
GitHub (opens new window)
  • Lean in c++

  • Performance Engineering

  • Misc

  • Reading Notes

    • Effective C++

    • More Effective C++

      • 基础议题
        • 基础议题
          • Item 1:区别 pointers和 references
          • Item 2:尽量使用C++的Cast操作符而不是C的
          • Item 3:不以多态(polymorphically)方式处理数组
          • Item 4:非必要不提供 default constructor
      • 操作符(operators)
      • 异常(exceptions)
      • 效率(efficiency)
      • 技术(techniques, idioms, patterns)
      • 杂项讨论,Misc
    • 《C++ 性能优化指南》
  • Wiki
  • Reading Notes
  • More Effective C++
Quincy Jet
2022-06-27
Content

基础议题

#

# 基础议题

# Item 1:区别 pointers和 references

  • references 必须有初值,pointer是可以没有初值的;(reference 一定得代表某个对象)
 ```cpp
 string &rs // 错误
 
 string s("hello");
 string& rs=s; // 正确
 
 string* ps; // 正确
 ```
  • 用references 可能会比使用pointers 更高效。因为使用 reference 之前不需要测试其有效性, 如果是指针, 需要判断是否为nullptr, if(pc),

  • Pointers 和 references 之间的一个重要差异是,pointers 可以被重新赋值指向另一个对象,reference 却总是指向(代表)它最初获得的那个对象

  • 先考虑用pointer, 如果真的是指向一个不变的东西, 或者pointer办不到的时候, 再考虑使用referenc

# Item 2:尽量使用C++的Cast操作符而不是C的

优先使用C++的cast操作: static_cast(), const_cast(), reinterprete_cast(), dynamic_cast();

  • static_cast 基本上拥有与 C 旧式转型相同的威力与意义,以及相同的限制。

  • const_cast 用来改变一个变量的常量性(constness)或变易性(volatileness)

  • dynamic_cast,用来“安全地向下转型或跨系转型动作”。也就是说可用dynamic_cast,将“指向base class objects的pointers或 references”转型为“指向 derived(或 sibling base)class objects的 pointers 或 references”,并能够通过返回值得知转型是否成功(0 or 1)

    • 具体到函数的传参上面使用, 其实就是多态的相反的用法:

      update(&csw);
      update(const_cast<SpecialWidget*>(&csw));   // 转移const属性;
      update(dynamic_cast<SpecialWidget*>(&csw)); // 从父类cast到子类;
      
      1
      2
      3
  • reinterpret_cast转换结果几乎总是与编译平台息息相关。所以reinterpret_casts不具移植性。reinterpret_cast的最常用的地方是转换“函数指针”。

# Item 3:不以多态(polymorphically)方式处理数组

不要以多态的方式处理数组, 因为多态的时候, 导致数组里面元素的大小不一样, 在数组里面slicing会导致便偏移错误;

// sample code
class BST{ ... };
class BalancedBST : public BST{ ... };

void printBSTArray(ostream &s, const BST array[], int numElements){
 for(int i=0; i<numElement; i++){
     s << array[i];  // 假设BST Objects有一个operator可用
 }
}

BST BSTArray[10];
PrintBSTArray(cout, BSTArray, 10);  // 运行良好

BalancedBST bBSTArray[10];
printBSTArray(cout, bBSTArry, 10); // 多态方式处理, 不可以, 结果未定义

// 如果删除
void deleteArray(ostream &logstream, BST array[]){
 logStream << "Deleting array at address, " << static_cast<void*>(array) << "\n";
 delete [] array;
}

BalancedBST *balTreeArray = new BalancedBST[50]; // 产生一个子类数组;
deleteArray(cout, balTreeArray); // 这样通过父类指针去删除子类数组, 结果未定义;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

多态和指针算数不能够混用;

# Item 4:非必要不提供 default constructor

非必要不使用默认的default constructor(没有参数的ctor)

  • 在一个完美的世界中,凡可以“合理地从无到有生成对象”的 classes,都应该内含 default constructors,而“必须有某些外来信息才能生成对象”的 classes,则不必拥有 default constructors。但我们的世界毕竟不是完美的世界,所以我们必须纳入其他考虑。

  • 缺乏default constructor可能产生的问题

    class Equipement{
        public:
        	Equipement(int numEque);
    }
    
    1
    2
    3
    4
    • 在产生数组的时候。无法为数组中的对象指定 constructor 自变量,所以几乎不可能产生一个由 EquipmentPiece objects 构成的数组:

      Equipement bestPieces[10]; // 出错 没有办法调用default ctor
      Equipement *bestPieces = new EquipementPiece[10]; // 出错
      
      1
      2
    • 这些class不适用于许多 template-based container classes。对那些 templates 而言,被实例化(instantiated)的“目标类型”必须得有一个 default constructors。

    • virtual base class constructors 的自变量必须由欲产生的对象的派生层次最深(所谓 most derived)的 class 提供。于是,一个缺乏 default constructor的 virtual base class,要求其所有的 derived classes——不论距离多么遥远——都必须知道、了解其意义,并且提供 virtual base class 的 constructors 自变量, 这是非常难做到的, 除非:

      // sample
      
      1
  • 添加无意义的default constructors也会影响class的效率;

  • 使其他的member function更加复杂

杂项, Misc
操作符(operators)

← 杂项, Misc 操作符(operators)→

Copyright © 2017-2023 Quincy Jet | MIT License
  • Auto
  • Light
  • Dark
  • Read