《Effective C++》(1-4)

条款01:视C++为一个语言联邦

Q. C++联邦由哪些次语言构成?

C:基础语法

面向对象:类、封装、继承、多态、虚函数等

模板:泛型编程和模板元编程(TMP)

STL:标准模板库,包含容器、迭代器、算法和函数对象的设计模式

Q. 为什么要视为语言联邦?

为了不同的子语言使用不同的编程习惯。

条款02:尽量以 constenuminline 替换 #define

补充:C11 之后 constexpr 更加强化了这一思想

Q. 为什么不建议在 C++ 中使用 #define 定义常量?

#define不做类型检查,宏展开可能导致难以发现的错误。而constenuminline 是类型安全的。

预处理后,代码中所有 宏名 都变成了 值 ,符号表没有宏名,调试器只会看到常量值,看不到宏名,调试时遇到报错只看到值很难定位。

Q. 推荐做法

  • enum是编译期常量不占内存编译期常量在编译阶段就已知具体数值,编译器会把它直接写到指令中(代码段),不用再存内存变量; 而运行期常量,必须在运行时算出来并存到数据段)
  • 宏函数应全部替换为 inlineconstexpr 函数。
  • 常量应首选 constexpr(支持编译期计算)或 inline constexpr(跨文件共享)
  • 宏定义的最佳实践是只在条件编译、平台特定代码中用宏(如 #ifdef _WIN32

条款03:尽可能使用 const

补充:C11 之后还可以结合 constexpr

Q. const 可以修饰哪些东西?为什么要“尽可能使用它”?

使用理由:

  • 防止无意修改数据

  • 增加可读性(一眼能看出这个变量是只读的)

  • 编译器优化(某些情况下可生成更高效代码)

 适用范围:

  • 变量   
    • const int a = 10; // 常量
  • 指针
    • 常量指针:int* const p;   //(p 不能改指向,但能改它指的值)
    • 指针常量:const int* p;   // 指向常量的指针(不能通过 p 改值)
    • 指向常量的常量指针:const int* const p; //(指向和值都不能改)
  • 函数参数
    • void func(const std::string& s); // 保证函数内部不会修改 s

  • 函数返回值
    • const std::string getName(); // 返回值不能作为左值修改

  • 成员函数
    • class A {
      public:
          int get() const; // 承诺不修改成员变量,对象调用 const 成员函数时,编译器会把 this 指针的类型改为 const A*
      };

 总体趋势:const 依然是基础工具,但现代C++更鼓励在编译期可知的值上用 constexpr(C11)/consteval(C20)

条款 04:确保对象在使用前被初始化

Q. C++ 中哪些变量如果你不手动初始化,它们的值是不确定的?

Q. 成员变量为什么要放在构造函数成员初始化列表里初始化,而不是在构造函数体内赋值?

初始化列表是在对象构造时直接初始化成员,而不是先默认构造再赋值。

Q. 静态对象(static 变量)什么时候初始化?如何确保它们按正确顺序初始化?

 
posted @ 2025-08-11 20:55  番茄玛丽  阅读(17)  评论(0)    收藏  举报