合集
- Part I 创建模式
- Chapter 2 Builder
- Chapter 3 Factory
- Chapter 4 Prototype
- Chapter 5 Singleton
- Part II Structural Patterns
- Chapter 6 Adapter
- Chapter 7 Bridge
- Chapter 8 Composite
- Chapter 9 Decorator
- Chapter 10 Facade
- Chapter 11 Flyweight
- Chapter 12 Proxy
- Part III Behavioral Patterns
- Chapter 13 Chain of Responsibility
- Chapter 14 Command
- Chapter 15 Interpreter
- Chapter 16 Iterator
- Chapter 17 Mediator
- Chapter 18 Memento
- Chapter 19 Null Object
- Chapter 20 Observer
- Chapter 21 State
- Chapter 22 Strategy
- Chapter 23 Template Method
- Chapter 24 Visitor
- Appendix A Functional Design Patterns
- Chapter 25 Maybe Monad
Part I 创建模式
下面是C++中创建对象的途径的一个综述:
栈分配Stack allocation 对象在栈中创建, 对象会在退出作用范围时被自动清理. 此时对象的析构函数会被自动调用 (这个行为有时会破坏Mementom模式), 我们会在后面讨论.
堆分配Heap allocation 使用原始指针(raw pointer) 指向在堆中分配的对象:
Foo *foo = new Foo;
会创建一个新的Foo
的实例, 并且将谁来负责释放它留给用户. GSL, https://github.com/Microsoft/GSL的owner<T>
尝试着将ownership
的概念引入到raw pointer中而不额外引入任何的cleanup code–你仍然必须自己来写清理代码.unique指针 (unique_ptr) 会使用堆分配的指针并管理它, 使得当它不再被使用时会自动清理. unique_ptr具有唯一性: 你不能拷贝它, 也不能将它传递给其他的函数的同时不放弃对它的控制.
shared指针 (shared_pointer) 使用并管理堆分配的指针, 并允许共享指针. 只有当没有其他的组件再持有这个指针时才会清理
weak指针 (weak_ptr) 没有所有权概念的指针, 持有一个由
shared_ptr
所管理的对象的弱引用. 要真正访问指针指向的内容, 需要先将其转换未shared_ptr
. 它主要的用途时打断shared_ptr
的循环引用.
从函数中返回对象
当需要在函数中返回大于word的数据时, 有几种方法.
首先, 最常见的直接返回:
1 | Foo make_foo(int n) |
它创建了Foo
的一份拷贝, 看上去似乎会浪费内存资源, 但实际上并不一定. 看下面的代码:
1 | struct Foo |
你会看到Foo
的拷贝构造函数执行的次数在0-2之间: 实际执行的次数取决于你使用的编译器.
返回值优化(Return Value Optimization, RVO) 是编译器特性, 它会阻止额外的拷贝.
在复杂的场景中, 你不应依赖于编译器的RVO特性, 但是在考虑是否要优化返回值时, 我更建议你遵守Knuth原则:
Donald Knuth, 在其著名的The Art of Computer Programming系列中曾经提到: “过早进行的优化时万恶之源 (premature optimization is the root of evil)”. C++所具有的过早优化能力格外诱人, 但是你应坚持这一原则, 直到: A) 你确切的知道自己在做什么. B) 你的确遇到了性能问题而需要优化性能.
另一种方法时返回指向对象的智能指针, 例如unique_ptr
1 | unique_ptr<Foo> make_foo(int n) |
这种做法很安全, 但是它提出一个问题: 为什么要使用unique_ptr
? 如果人们更想用shared_ptr
该怎么办?
最后一种做法是使用原始指针 (raw pointer), 可能的一种做法是是哟个GSL的owner<T>
. 这种方式, 你并没有强制要求对分配对象的清理工作, 但是你清晰的表达了这样一个意思: 释放对象的资源是调用者的责任
1 | owner<Foo*> make_foo(int n) |
Chapter 2 Builder
@import “Chapter_02_Builder.md”
Chapter 3 Factory
@import “Chapter_03_Factories.md”
Chapter 4 Prototype
@import “Chapter_04_Prototype.md”
Chapter 5 Singleton
@import “chapter_05_Singleton.md”
Part II Structural Patterns
@import “Part_2_Structural Patterns.md”
Chapter 6 Adapter
@import “chapter_06_Adapter.md”
Chapter 7 Bridge
@import “chapter_07_Bridge.md”
Chapter 8 Composite
@import “chapter_08_Composite.md”
Chapter 9 Decorator
@import “chapter_09_Decorator.md”
Chapter 10 Facade
@import “chapter_10_Facade.md”
Chapter 11 Flyweight
@import “chapter_11_Flyweight.md”
Chapter 12 Proxy
@import “chapter_12_Proxy.md”
Part III Behavioral Patterns
@import “part_3_Behavioral_Patterns.md”
Chapter 13 Chain of Responsibility
@import “chapter_13_Chain_of_Responsibility.md”
Chapter 14 Command
@import “chapter_14_Command.md”
Chapter 15 Interpreter
@import “chapter_15_Interpreter.md”
Chapter 16 Iterator
@import “chapter_16_Iterator.md”
Chapter 17 Mediator
@import “chapter_17_Mediator.md”
Chapter 18 Memento
@import “chapter_18_Memento.md”
Chapter 19 Null Object
@import “chapter_19_Null_Object.md”
Chapter 20 Observer
@import “chapter_20_Observer.md”
Chapter 21 State
@import “chapter_21_State.md”
Chapter 22 Strategy
@import “chapter_22_Strategy.md”
Chapter 23 Template Method
@import “chapter_23_Template_Method.md”
Chapter 24 Visitor
@import “chapter_24_Visitor.md”
Appendix A Functional Design Patterns
@import “Appendix_A_Functional_Design_Pattern.md”
Chapter 25 Maybe Monad
@import “chapter_25_Maybe_Monad.md”