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++

      • 习惯C++
        • 习惯C++
          • Item 01:视C++为一个语言联邦, View C++as a federation of languages.
          • Item 02:尽量以const,enum,inline替换#define, Prefer consts,enums,and inlines to#defines.
          • Item 03:尽可能使用const, Use const whenever possible.
          • Item 04:Make sure that objects are initialized before they're used. 对象在使用前已先被初始化
      • 构造,析构, 和重载赋值运算符
      • 资源管理
      • 设计与声明
      • 实现Implementations
      • 继承与OOP
      • 模板,Templates and GP
      • 定制new和delete
      • 杂项, Misc
    • More Effective C++

    • 《C++ 性能优化指南》
  • Wiki
  • Reading Notes
  • Effective C++
Quincy Jet
2022-06-27
Content

习惯C++

# 习惯C++

# Item 01:视C++为一个语言联邦, View C++as a federation of languages.

C++是一个语言联邦, 有多种编程范式: procedural (面向过程), OOP(面向对象), GP(泛型编程), Functional Programming(函数式编程),metaprograming(元编程),但差不多有四个主要的部分:

  1. C:数组, 指针, 预处理, 程序员的自我修养
  2. Object oriented C++: classs, encapsulation, ingeritance, polymorphism, virtual function的动态绑定;(模板, 异常, 重载)
  3. Template C++ (template metaprogramming, 模板元编程)
  4. STL: 容器(containers)、迭代器(iterators)、算法(algorithms)以及函数对象(function objects)

# Item 02:尽量以const,enum,inline替换#define, Prefer consts,enums,and inlines to#defines.

用const, enum, inline代替 #define

  1. const 能够更好地控制指针和指针所指变量的const属性, 并且#define对作用域不敏感,const可以定义某个类专属的常量;

    const int GamePlayer::NumTurns;
    
    1
  2. class专属常量。为确保此常量至多只有一份实体,你必须让它成为一个static成员:

    class GamePlayer{
    	private:
    		static const int NumTurns = 5; // 常量声明
    		int scores[NumTurns]; // 使用该常量
    }
    
    1
    2
    3
    4
    5
  3. enum是不可以取地址的,enum hack是模板原编程的基础技术,见Item 48

  4. #define带来的安全性可以使用模板inline函数实现, 见Item 30

    template<typename T> // 暂时用模板的typename代替
    inline void callWithMax(const T& a, const T& b){
        f(a > b ? a : b);
    }
    
    1
    2
    3
    4
  5. 对于单纯常量,最好以const对象或enums替换#defines。

  6. 对于形似函数的宏(macros),最好改用inline函数替换#defines。

# Item 03:尽可能使用const, Use const whenever possible.

该用const的地方,尽可能使用const

  1. 类内的变量是否为const?

  2. 指针的双重const, 在什么之前就修饰什么, 指针为const, 还是指针指向的值为const, 常量指针

    const char* const authorName = "Quincy"
    
    1
  3. 函数的参数是否传const引用? 使用const修饰, 会明示参数是否被改变(引用不改变, 要加const表示出来);

  4. 成员函数后是加const, 代表这个成员函数不会修改类内的值;

  5. 返回值是否要成为const(为什么?), 看返回值类型是否是需要const不允许变动(防止用户自身的村务使用, 不放弃高效性), 其次是避免成为左值被修改;

a.get_data()=3;  // 返回一个const, 这种操作就是不合法的;
1
  1. mutable可以释放掉non-static成员变量的bitwise constness约束;

    class CTextBlock{
        public:
        	std::size_t length() const;
        private:
        	char* pText;
        	mutable std::size_t textLength; //这些变量可能总是会被改变
    	    mutable bool lengthIsValis;
    // 在length()中, 会频繁改变上述的两个变量;  
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

    Key:

    • 将某些东西声明为const可帮助编译器提示出错误用法。const可被施加于任何作用域内的对象、函数参数、函数返回类型、成员函数本体。

    • 编译器强制实施bitwise constness,但你编写程序时应该使用“概念上的常量性”(conceptual constness)。

    • 当const和non-const成员函数有着实质等价的实现时(确实是要有两个版本),令non-const版本调用const版本可避免代码重复。因为const可以兼容non-const的输入, 但是non-const不可以兼容const的输入

      class TextBlock {
      public:
          ...
          const char& operator[](std::size_t position) const // 表示不改变类成员
          {
              ... // do bounds checking
              ... // log access data
              ... // verify data integrity
              return text[position];
          }
          char& operator[](std::size_t position)
          {
              ... // do bounds checking
              ... // log access data
              ... // verify data integrity
              return text[position];
          }
      private:
          std::string text;
      };
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20

# Item 04:Make sure that objects are initialized before they're used. 对象在使用前已先被初始化

  1. 没有初始化的值,在读它的时候会导致不明确的行为, 变量里面包含的内容都是半随机状态;

  2. 在初始化列表里面, 列出所有的成员变量, 免得遗漏, 除非记得住哪些不用初始值;

    1. 实在太多的话, 用一个private函数包一下能够赋值处理的, 也可以;
    2. 初始化的顺序总是按照声明顺序来, 不是按照初始化列表的顺序
  3. 成员变量是const或者reference, 就一定要初始化, 因为后面不能再被赋值了;

  4. 如果有一个non-local static对象, 没有办法保证是否使用的时候已经初始化, 那就在本地搞一个static函数(处理static对象的函数叫做static的函数)把这个对象包起来,返回一个指向这个对象的reference, 这样, 外部的static对象就变成了本地的static对象, 这也是singleton模式的一个常见实现手法(这种手法叫做reference returning)

    Directory& tempDir(){
    	static Directory& td; // more effective c++里面, 限制对象数目的方式, 好像是一样的
    	return td; // 还是把non-loca的static的对象,改变成local static的对象比较好;
    }
    
    1
    2
    3
    4
  5. 任何一种non const static 对象,在多线程环境下, 都会有线程安全的问题;non const代表了可以被改变, 多线程可以同时改变它;

VsCode 常用插件
构造,析构, 和重载赋值运算符

← VsCode 常用插件 构造,析构, 和重载赋值运算符→

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