Skip to the content.

Supported Platforms Build Status GitHub license

Build

git clone git@github.com:downdemo/Design-Patterns-in-Cpp17.git
cd Design-Patterns-in-Cpp17
cmake . -Bbuild
cd build
cmake --build .

设计模式简介

Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice.

创建型模式 中文名 说明 实现
Abstract Factory/Kit 抽象工厂模式 README C++
Builder 建造者模式 README C++
Factory Method/Virutal Contructor 工厂方法模式 README C++
Prototype 原型模式 README C++
Singleton 单例模式 README C++
结构型模式 中文名 说明 实现
Adapter/Wrapper 适配器模式 README C++
Bridge/Handle/Body 桥接模式 README C++
Composite 组合模式 README C++
Decorator/Wrapper 装饰器模式 README C++
Facade 外观模式 README C++
Flyweight 享元模式 README C++
Proxy/Surrogate 代理模式 README C++
行为型模式 中文名 说明 实现
Chain of Responsibility 责任链模式 README C++
Command/Action/Transaction 命令模式 README C++
Interpreter 解释器模式 README C++
Iterator/Cursor 迭代器模式 README C++
Mediator 中介者模式 README C++
Memento/Token 备忘录模式 README C++
Observer/Dependents/Publish-Subscribe 观察者模式 README C++
State/Objects for States 状态模式 README C++
Strategy/Policy 策略模式 README C++
Template Method 模板方法模式 README C++
Visitor 访问者模式 README C++

C++ 中的设计模式

class B;

class A {
 public:
  std::shared_ptr<B> b;
  ~A() { std::cout << "Destroy A\n"; }
};

class B {
 public:
  std::shared_ptr<A> a;
  ~B() { std::cout << "Destroy B\n"; }
};

int main() {
  {
    auto p = std::make_shared<A>();
    p->b = std::make_shared<B>();
    p->b->a = p;
    assert(p.use_count() == 2);
  }  // p 的引用计数由 2 减为 1,不会析构
     // 于是 p->b 也不会析构,导致两次内存泄漏
}
class B;

class A {
 public:
  std::shared_ptr<B> b;
  ~A() { std::cout << "Destroy A\n"; }
};

class B {
 public:
  std::weak_ptr<A> a;
  ~B() { std::cout << "Destroy B\n"; }
};

int main() {
  {
    auto p = std::make_shared<A>();
    p->b = std::make_shared<B>();
    p->b->a = p;  // weak_ptr 不增加 shared_ptr 的引用计数
    assert(p.use_count() == 1);
  }  // Destroy A
     // Destroy B
}

检测内存泄漏的方法

#include <crtdbg.h>

#ifdef _DEBUG
#define new new (_NORMAL_BLOCK, __FILE__, __LINE__)
#endif

int main() {
  int* p = new int(42);
  _CrtDumpMemoryLeaks();
}
Detected memory leaks!
Dumping objects ->
xxx.cpp(9) : {88} normal block at 0x008C92D0, 4 bytes long.
 Data: <*   > 2A 00 00 00 
Object dump complete.
#include <crtdbg.h>

#include <memory>

#ifdef _DEBUG
#define new new (_NORMAL_BLOCK, __FILE__, __LINE__)
#endif

int main() {
  auto p = std::make_shared<int>(42);
  _CrtDumpMemoryLeaks();  // 此时 std::shared_ptr 还未析构,因此报告内存泄漏
}
#include <crtdbg.h>

#ifdef _DEBUG
#define new new (_NORMAL_BLOCK, __FILE__, __LINE__)
#endif

int main() {
  _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG));
  int* p = new int(42);
}

智能指针的传参方式选择

void f(std::shared_ptr<A> p);         // 按值传递
void f(const std::shared_ptr<A>& p);  // 按 const 引用传递
void f(A&);  // 仅使用对象,不涉及对象资源所有权的管理
void f(A*);  // 仅使用对象,不涉及对象资源所有权的管理

void f(std::unique_ptr<A>);  // 用于转移唯一所有权(用 std::move 传入)
void f(std::unique_ptr<A>&);        // 用于重置内部对象
void f(const std::unique_ptr<A>&);  // 不如直接传引用或原始指针

void f(std::shared_ptr<A>);   // 引用计数共享
                              // 可用 std::move 传入 std::unique_ptr 实参
void f(std::shared_ptr<A>&);  // 引用计数不变,用于重置内部对象
                              // 不可接受 std::unique_ptr 实参
void f(const std::shared_ptr<A>&);  // 引用计数不变,不可重置内部对象
                                    // 可用 std::move 传入 std::unique_ptr 实参
void f(const std::shared_ptr<A>& p) {
  auto q = p;  // 拷贝 p
  // ...
}
void f(std::shared_ptr<A> p) {  // 拷贝一次
  auto q = std::move(p);        // 移动一次
  // ...
}
class X {
 public:
  explicit X(std::shared_ptr<A> p) : p_(std::move(p)) {}

 private:
  std::shared_ptr<A> p_;
};