![](https://img-blog.csdnimg.cn/20201014180756922.png?x-oss-process=image/resize,m_fixed,h_224,w_224)
1.3.6《深入应用C++11》
文章平均质量分 51
1.3.6《深入应用C++11》
vimer-hz
书是越读越薄的
展开
-
[16 使用C++11开发一个简单的通信程序(Proactor模式)] 16.5 C++11结合asio实现一个简单的客户端程序
客户端的需求:具备读/写能力,能自动重连。自动重连用一个线程去检测,读/写能力复用RWHandler。客户端的实现如下:class Connector{public: Connector(io_service& ios, const string& strIP, short port) : m_ios(ios), m_socket(ios), m_serverAddr(tcp::endpoint(address::from_string(strIP), port))转载 2021-07-21 11:58:42 · 489 阅读 · 0 评论 -
[16 使用C++11开发一个简单的通信程序(Proactor模式)] 16.4 C++11结合asio实现一个简单的服务端程序
需求:服务端监听某个端口,允许多个客户端连接上来,打印客户端发来的数据。转载 2021-07-21 10:25:10 · 460 阅读 · 0 评论 -
[16 使用C++11开发一个简单的通信程序(Proactor模式)] 16.3 asio的基本用法
asio的异步操作过程如下:todo图16-7 asio的异步操作过程(1)应用程序发起了一个异步请求(异步读或写),需要提供socket或异步操作完成函数。(2)asio的io_object对象会将这个异步请求交给操作系统,由操作系统完成该请求。(3)调用io-service::run等待异步事件的完成。(4)操作系统完成异步操作后,将异步操作的结果返回给io_service。(5)io_service将完成事件的结果回调到对应的完成函数并处理。用户要发起一个异步操作需要做转载 2021-07-19 15:53:31 · 472 阅读 · 0 评论 -
[12 使用C++11开发一个对象的消息总线(观察者模式和中介者模式的应用及优化)] 12.2 消息总线关键技术
对象之间的关系:依赖,关联,聚合,组合和继承,耦合关系依次加强。12.2 消息总线关键技术12.2.1 通用的消息定义消息类型定义:主题+泛型函数的签名主题可以是字符串或整型等其他类型;这里将泛型函数定为std::function<R(Args...)>,R表示函数返回值,Args表示函数可变入参。泛型函数能表示所有的可调用对象,表示通用的消息格式。如下将可调用对象转换为std::function,用到特性萃取function_traits:#include<fu转载 2021-07-14 10:04:36 · 1221 阅读 · 0 评论 -
[16 使用C++11开发一个简单的通信程序(Proactor模式)] 16.1 Reactor反应器模式和Proactor主动器模式介绍
libevent是基于Reactor(反应器)模式实现的,asio是基于Proactor(主动器)模式实现的。1 Reactor反应器反应器模式的类图:todo图16-1反应器模式的类图反应器模式的流程如下:(1)应用程序在反应器上注册具体事件处理器,处理器提供内部句柄给反应器。(2)应用程序开始启动反应器事件循环。反应器将通过select等待发生在句柄集上的事件。(3)当一个或多个句柄编程就绪状态时,反应器将通知注册的具体事件处理器。(4)具体事件处理器处理事件,完..转载 2021-07-16 13:00:05 · 633 阅读 · 0 评论 -
[12 使用C++11开发一个对象的消息总线(观察者模式和中介者模式的应用及优化)] 12.4 应用实例
假设有3个对象Car,Bus,Truck,都向消息总线注册了消息,消息类型为std::function<void(int)>,其中Car,Bus在注册时指定了主题。这三个对象在注册完消息后,希望能收到感兴趣的消息并处理,并不关心是谁给他们发送消息;另外,有个Subject会发送消息,Subject并不关心实惠收到消息。3个对象和Subject对象没有耦合关系,它们之间唯一的联系就是消息总线。MessageBus的一个应用示例如下:#include "MessageBus.hpp"M转载 2021-07-14 14:19:36 · 329 阅读 · 0 评论 -
[12 使用C++11开发一个对象的消息总线(观察者模式和中介者模式的应用及优化)] 12.3 完整的消息总线
完整的MessageBus实现:#include <string>#include <functional>#include <map>#include "Any.h"#include "function_traits.h"#include "NonCopyable.h"using namespace std;class MessageBus : NonCopyable{public: // 注册消息 template<t转载 2021-07-14 11:21:35 · 343 阅读 · 0 评论 -
[11 使用C++11开发一个轻量级的IoC容器(工厂模式的应用及优化)] 11.6 完整的IoC容器
通过可变参数模板改进IoC容器,让它支持带参数对象的创建:#include <string>#include <unordered_map>#include <memory>#include <functional>using namespace std;#include "Any.hpp" #include "NonCopyable.hpp" class IocContainer : NonCopyable{public:转载 2021-07-09 17:29:37 · 533 阅读 · 0 评论 -
[11 使用C++11开发一个轻量级的IoC容器(工厂模式的应用及优化)] 11.4 通过Any和闭包来擦除类型 和 创建依赖的对象
11.2节的对象工厂只能创建指定接口类型的对象,原因是它依赖了一个类型固定的对象构造器std::function<T*()>,这个function作为对象构造器只能创建T类型的对象,不能创建所有类型的对象。我们可以通过Any类来使map存放所有类型的对象。Any类的基本用法如下:Any a = 1;Any b = 1.25;Any c = "string";std::vector<Any> v = {a, b, c};// 用的时候转换回来if (a.Is<i转载 2021-07-09 12:47:27 · 286 阅读 · 0 评论 -
[11 使用C++11开发一个轻量级的IoC容器(工厂模式的应用及优化)] 11.3 类型擦除的常用方法
类型擦除就是将原有类型消除或隐藏。类型擦除可以使得程序获得更好的扩展性,消除耦合。下面是常见的类型擦除方式:1 多态2 模板3 类型容器Variant4 通用类型Any5 闭包1 多态通过将派生类型隐式转换为基类型,再通过基类去调用虚函数。这样就把派生类型转成基类型隐藏起来。多态方式的类型擦除只是部分擦除,因为基类型还在;且需要继承关系,强耦合。2 模板本质上是把不同类型的共同行为进行了抽象,不需要再通过继承这种强耦合方式去获取共同的行为。存在的问题是,不能把T本转载 2021-07-09 09:45:05 · 302 阅读 · 0 评论 -
[11 使用C++11开发一个轻量级的IoC容器(工厂模式的应用及优化)] 11.2 IoC创建对象
一个可配置的对象工厂实现思路如下:1 先注册可能需要创建对象的构造函数,将其放到一个内部关联容器map中,设置键为类型的名字,值为类型的构造函数。2 然后在创建的时候根据类型名称查找对应的构造函数并最终创建出目标对象。可配置的对象工厂如下:#include <string>#include <map>#include <memory>#include <functional>using namespace std;template&l转载 2021-07-08 16:52:52 · 302 阅读 · 1 评论 -
[11 使用C++11开发一个轻量级的IoC容器(工厂模式的应用及优化)] 11.1 IoC容器是什么
工厂模式的定义:定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。类图如下:参考网址:http://c.biancheng.net/view/1348.html转载 2021-07-07 17:58:41 · 532 阅读 · 1 评论 -
[10 使用C++11开发一个轻量级的AOP库] 代理模式的应用
代理模式的定义:由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。代理模式的主要优点有:1 代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用;2 代理对象可以扩展目标对象的功能;3 代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度,增加了程序的可扩展性其主要缺点是:1 代理模式会造成系统设计中类的数量增加2 在客户端和目标对象之间增加一个代理对象,会造成请求处理转载 2021-07-06 17:16:24 · 416 阅读 · 1 评论 -
[9 使用C++11开发一个半同步半异步线程池]
9.1 半同步半异步线程池介绍传统的一个请求一个线程处理,在处理大量并发任务时,会导致大量的线程创建和销毁,消耗过多的系统资源。线程池可以解决这个问题。本章介绍的是半同步半异步线程池,线程池结构图如图9-1:todo图9-1 半同步半异步线程池第一层是同步服务层,它处理来自上层的任务请求。上层的请求可能是并发的,这些请求不是马上被处理,而是将这些请求放到一个同步队列里。第二层是排队层,即同步队列。第三层是异步服务层,多个线程从同步队列里取出任务并处理。9.2 线程池实现的转载 2021-07-06 14:26:12 · 148 阅读 · 0 评论 -
[8 使用C++11改进我们的模式] 8.3 改进访问者模式
访问者(Visitor)模式的定义:将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作。它将对数据的操作与数据结构进行分离,是行为类模式中最复杂的一种模式。访问者(Visitor)模式是一种对象行为型模式,其主要优点如下。1 扩展性好。能够在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能。2 复用性好。可以通过访问者来定义整个对象结构通用的功能,从而提高系统的复用程度。3 灵活性好。访问者模式将数据结构与作用于结转载 2021-07-05 10:39:48 · 177 阅读 · 0 评论 -
[8 使用C++11改进我们的模式] 8.2 改进观察者模式
观察者(Observer)模式的定义:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式,它是对象行为型模式。观察者模式是一种对象行为型模式,其主要优点如下。1 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。符合依赖倒置原则。2 目标与观察者之间建立了一套触发机制。它的主要缺点如下。1 目标与观察者之间的依赖关系并没有完全解除。2 当观察者对象很多时,通知的发布会花费很多时间,影响程序的转载 2021-07-02 12:44:44 · 283 阅读 · 2 评论 -
[8 使用C++11改进我们的模式] 8.1 改进单例模式
定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。类图:C++11前,实现一个通用的泛型单例模式,支持0~3的单例如下:template <typename T>class Singleton{public: // 支持0个参数的构造函数 static T* Instance() { if (m_pInstance == null) m_pInstance = new T(); re转载 2021-07-02 09:29:28 · 200 阅读 · 0 评论 -
[5 使用C++11让多线程开发变得简单] 5.7 线程异步操作函数 std::async
std::async比std::promise,std::packaged_task更高一层,它可以创建异步的task,异步任务返回的结果也保存在future中。当获取异步任务的结果时,调用future.get();不关注异步任务的结果,只等待任务完成的话,调用future.wait()。async的声明:async(std::launch::async | std::launch::deferred, f, args...)(1)第一个参数:线程的创建策略std::launch::as转载 2021-06-30 12:55:27 · 188 阅读 · 0 评论 -
[5 使用C++11让多线程开发变得简单] 5.6 异步操作类 std::future,std::promise,std::package_task
std:future作为异步结果的传输通道,用来获取线程函数的返回值;std::promise用来包装一个值,将数据和future绑定起来;std::package_task用来包装一个可调用对象,将函数和future绑定起来。5.6.1 std::futurethread库提供了future用来访问异步操作的结果。因为一个异步操作的结果不能马上获取,只能在未来某个时刻从某个地方获取,这个异步操作的结果是一个未来的期待值,所以被称为future。我们可以以同步等待的方式来获取结果,可转载 2021-06-30 09:39:28 · 195 阅读 · 0 评论 -
[5 使用C++11让多线程开发变得简单] 5.5 call_once/once_flag的使用
std::call_once用来保证函数在多线程环境中只被调用一次。使用std::call_once时,需要一个once_flag作为call_once的入参。#include <iostream>#include <thread>#include <mutex>std::once_flag flag;void do_once(){ std::call_once(flag, [](){ std::cout << "Called转载 2021-06-29 16:01:03 · 151 阅读 · 0 评论 -
[5 使用C++11让多线程开发变得简单] 5.3 条件变量
条件变量能阻塞线程(wait),直到收到另一个线程发出的通知或超时,才会唤醒当前阻塞的线程。C++11提供了两种条件变量:(1)condition_variable,wait函数需要与std::unique_lock<std::mutex>配合使用(2)conditon_vatiable_any,可和任意mutex配合使用,更灵活,但效率较低条件变量的使用过程:(1)拥有条件变量的线程获取互斥量(2)循环检查某个条件,如果条件不满足,则阻塞直到条件满足;如果条件满足,转载 2021-06-29 14:07:05 · 423 阅读 · 0 评论 -
[5 使用C++11让多线程开发变得简单] 5.2 互斥量
C++11提供如下4中语义的互斥量:std::mutex:独占互斥量,不能递归使用。std::timed_mutex:带超时的独占互斥量,不能递归使用。std::recursive_mutex:递归互斥量。std::recursive_timed_mutex:带超时的递归互斥量。5.2.1 独占互斥量std::mutexlock阻塞的;try_lock非阻塞的,尝试锁定互斥量,成功返回true,失败返回false。std::mutex的基本用法:#include <转载 2021-06-28 17:24:36 · 207 阅读 · 0 评论 -
[5 使用C++11让多线程开发变得简单] 5.1 线程
std::thread创建线程很简单,只需提供线程函数或函数对象,同时指定线程函数的参数。创建线程示例:#include <thread>void func(){}int main(){ std::thread t(func); t.join(); return 0;}join函数会阻塞主线程,直到子线程执行结束。如果不希望主线程被阻塞,可用detach()方法,将主线程和子线程分离。#include <thread>转载 2021-06-28 15:44:56 · 107 阅读 · 0 评论 -
[2 使用C++11改进程序性能] 2.5 unordered container
C++11新增无序容器unordered_map/unordered_multimap和unordered_set/unordered_multiset,因为无需排序,比有序容器map/multimap和set/multiset效率高。map和set底层实现是红黑树,插入元素时会自动排序;unordered_map和unordered_set底层是哈希表,通过哈希来操作元素,效率更高。因为无序容器底层实现是哈希表,所以对于自定义的key,需要提供Hash函数和比较函数;对于基本类型已实现,无需提供。转载 2021-06-28 14:30:14 · 101 阅读 · 0 评论 -
[2 使用C++11改进程序性能] 2.4 emplace_back
emplace_back能就地通过参数构造对象,不需要拷贝构造,相比push_back性能提升。转载 2021-06-28 10:58:23 · 286 阅读 · 0 评论 -
[2 使用C++11改进程序性能] 2.3 forward
完美转发,是指在函数模板中,完全依照模板的参数类型(即保持参数的左值,右值特征),将参数传递给函数模板中的另一个函数。转载 2021-06-26 14:21:40 · 131 阅读 · 0 评论 -
[2 使用C++11改进程序性能] 2.2 move语义
std::move方法来讲左值转换为右值。move是将对象的状态或所有权从一个对象转移到另一个对象,只是转移,没有内存拷贝。move语义的作用:对于一个对象中有一些指针资源,在对象的复制或拷贝时就不需要拷贝这些资源了。C++11之前赋值函数:A& A::operator=(const A& rhs){ // 销毁m_ptr指向的资源 // 复制rhs.m_ptr指向的资源,并使m_ptr指向它}move语义:A& A::operator=(转载 2021-06-23 14:25:36 · 189 阅读 · 0 评论 -
[2 使用C++11改进程序性能] 2.1 右值引用
C++11中引入右值引用和移动语义,可以避免无谓的复制,提高程序性能。2.1 右值引用C++11新增类型,右值引用,标记为T &&。转载 2021-06-22 16:34:00 · 189 阅读 · 0 评论 -
[1 使用C++11让程序更简洁] 1.6 lambda表达式
1.6 lambda表达式转载 2021-06-19 17:24:56 · 140 阅读 · 0 评论 -
[1 使用C++11让程序更简洁] 1.5 std::function和std::bind绑定器
1.5.1 可调用对象可调用对象有如下定义:(1)一个函数指针。(2)一个具有opetator()成员函数的类对象(仿函数)。(3)一个可被转换为函数指针的类对象。(4)一个类成员指针。void func(void){ // ...}struct Foo{ void operator()(void) { // ... }};struct Bar{ using fr_t = void(*)(void);转载 2021-06-18 10:32:11 · 192 阅读 · 0 评论 -
[1 使用C++11让程序更简洁] 1.1 类型推导(auto和decltype)
1.1 类型推导1.1.1 auto类型推导3. auto的限制void func(auto a =1) {} //error: auto不能用于函数参数struct Foo{ auto var = 0; //error: auto不能用于非静态成员变量 static const auto var1 = 0; //ok}template <typename T>struct Bar {};int main(){转载 2021-06-12 20:29:31 · 159 阅读 · 0 评论 -
[1 使用C++11让程序更简洁] 1.3 列表初始化
为了统一C++03的初始化方式,C++11提出了列表初始化。1.3.1 统一的初始化对于普通数组和POD类型(plain old data类型,即可以直接使用memcpy复制的对象),C++03是可以使用初始化列表进行初始化的:int arr[] = {1, 2, 3};struct A{ int x; int y;} a = {1, 2};C++11可以用于任何类型对象的初始化列表:class Foo{ public: Foo(in转载 2021-06-12 20:26:18 · 128 阅读 · 0 评论 -
[1 使用C++11让程序更简洁] 1.2 模板的细节改进(using别名)
1.2.2 模板的别名typedef重定义类型:typedef unsigned int uint_t但它有一些限制,例如,定义一个模板很丑陋:typedef std::map<std::string, int> map_int_t;typedef std::map<std::string, std::string> map_str_t;// 我们需要一个key为std::string的map模板,用typedef写法如下template <typen转载 2021-06-10 12:56:52 · 216 阅读 · 0 评论 -
[4 使用C++11解决内存泄漏问题] 4.1 shared_ptr / 4.2 unique_ptr / 4.3 weak_ptr
智能指针是存储指向动态分配(堆内存)对象指针的类。通用实现技术是使用引用计数。每使用它一次,引用计数加1,每析构一次,引用计数减1,减为0时,删除所指向的堆内存。C++11提供三种智能指针,std::shared_ptr,std::unique_prt和std::weak_ptr。需引用头文件<memory>。4.1 shared_ptr共享的智能指针shared_ptr使用引用计数,每一个shared_ptr的拷贝都指向相同的内存。在最后一个shared_ptr析构时,内.转载 2021-05-28 12:42:30 · 468 阅读 · 0 评论