委托构造

class DemoDelegating final            // final 防止类被继承
{
private:
	int a;                              // 成员变量
public:    
	DemoDelegating(int x) : a(x)        // 基本的构造函数    
	{}

  DemoDelegating() :                 // 无参数的构造函数        
		DemoDelegating(0)               // 给出默认值,委托给第一个构造函数    
	{}      

	DemoDelegating(const string& s) : // 字符串参数构造函数        
		DemoDelegating(stoi(s))        // 转换成整数,再委托给第一个构造函数    
	{}
};

成员变量初始化

class DemoInit final                  // 有很多成员变量的类
{
private:
	int                 a = 0;        // 整数成员,赋值初始化
	string              s = "hello";  // 字符串成员,赋值初始化
	vector<int>         v{1, 2, 3};   // 容器成员,使用花括号的初始化列表
public:    
	DemoInit() = default;             // 默认构造函数
  ~DemoInit() = default;             // 默认析构函数
public:    
	DemoInit(int x) : a(x) {}         // 可以单独初始化成员,其他用默认值
};

类型别名

using uint_t = unsigned int;   // using 别名
typedef unsigned int uint_t;   // 等价于 using

RAII

C++ 支持将对象存储在栈上面。但是,在很多情况下,对象不能、或不应该,存储在栈上。比如:

  1. 对象很大
  2. 对象的大小在编译时不能确定
  3. 对象是函数的返回值,但由于特殊的原因,不应使用对象的值返回

所以可以利用栈展开的时候,在栈变量析构函数中释放内存。

在析构函数里做必要的清理工作,这就是 RAII 的基本用法。这种清理并不限于释放内存,也可以是:

  1. 关闭文件
  2. 释放同步锁
  3. 释放其他重要的系统资源

以下是一个工厂方法的案例,保证了返回对象能够有序的释放对象内存

#include <iostream>

using namespace std;

enum class ShapeType {
  circle,
  triangle,
  rectangle,
};

class Shape {};
class Circle : public Shape {};
class Triangle: public Shape {};
class Rectangle: public Shape {};

class ShapeWrapper {
 public:
  explicit ShapeWrapper(Shape* ptr = nullptr) : ptr_(ptr) {}  // explicit 避免隐式转换
  ~ShapeWrapper() {
    cout << "~ShapeWrapper" << endl;
    delete ptr_;  // 释放空指针会做判断,所以不会出错
  }  // 保证在析构的时候释放 ptr_

  Shape* get() const { return ptr_; }

 private:
  Shape* ptr_;
};

Shape* create_shape(ShapeType type) {
  switch (type) {
    case ShapeType::circle:
      return new Circle;
    case ShapeType::triangle:
      return new Triangle;
    case ShapeType::rectangle:
      return new Rectangle;
  }
  return nullptr;
}

void check_raii() {
  // 这里将 create_shape 返回的指针放到 Wrapper 中
  // 编译器会自动调用析构函数,包括在函数执行发生异常的情况。(栈展开)
  // 在函数退出时,对 栈变量 ptr 执行析构,释放 create_shape 申请的堆上的内存
  ShapeWrapper ptr(create_shape(ShapeType::circle));
}