<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[Max_Cong的博客]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/Max_Cong</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; Max_Cong]]></copyright><item><title><![CDATA[走进C++11（四十六）inline namespace]]></title><link>https://blog.youkuaiyun.com/Max_Cong/article/details/116881497</link><guid>https://blog.youkuaiyun.com/Max_Cong/article/details/116881497</guid><author>Max_Cong</author><pubDate>Sun, 16 May 2021 08:55:18 +0800</pubDate><description><![CDATA[关注公众号获取更多信息：





这篇文章是这个系列的最后一篇。这个系列是我第一次尝试写一个系列的文章。其中发现了很多不足的地方。回首之前的文章，在排版，内容形式等方面都很欠缺。之后我会努力呈现更好的内容。敬请期待。



最后的一篇留给了inline namespace。说起inline namespace不得不先说一下namespace， namespace最常用的就是C++标准的std名字空间。名字空间的作用是区别同名的全局成员，例如在两个头文件中声明了同名的函数，如果在其他地方同时包含了两个头..]]></description><category></category></item><item><title><![CDATA[走进C++11（四十五） thread_local]]></title><link>https://blog.youkuaiyun.com/Max_Cong/article/details/116881472</link><guid>https://blog.youkuaiyun.com/Max_Cong/article/details/116881472</guid><author>Max_Cong</author><pubDate>Sun, 16 May 2021 08:53:53 +0800</pubDate><description><![CDATA[关注公众号获取更多信息：





今天说说thread_local 关键字。



说到thread_local就要说到C++存储类说明符。C++有如下几种存储类说明符：



auto
			自动存储期（C++11前）
		register
			自动存储期，另提示编译器将此对象置于处理器的寄存器。(弃用)（C++17前）
		static
			静态或线程存储期和内部连接。
		extern
			静态或线程存储期和外部连接。
		thread_local
			线程存储期
		mutabl...]]></description><category></category></item><item><title><![CDATA[走进C++11（四十四） noexcept]]></title><link>https://blog.youkuaiyun.com/Max_Cong/article/details/116881447</link><guid>https://blog.youkuaiyun.com/Max_Cong/article/details/116881447</guid><author>Max_Cong</author><pubDate>Sun, 16 May 2021 08:52:45 +0800</pubDate><description><![CDATA[关注公众号获取更多信息：







好久没有没有更新文章了，因为最近忙于A,B,C.....好吧我摊牌了。就是因为懒。这个文章是这个系列的倒数第三篇文章。C++11系列更新完了之后，我会更新其他编程相关的文章。



言归正传，今天讲的是noexcept。这个关键字也是属于你不知道它也能编出好程序的，没有存在感的一个关键字，但是用好它会让你的程序更加清晰，它会告诉编译器，这个函数不可能抛出异常，这样编译器对你的程序做更多的优化。由于C++中的异常处理是在运行时而不是编译时检测的。为了实现运行时检测...]]></description><category></category></item><item><title><![CDATA[走进C++11（四十三）memory order 番外篇一 为什么实现同样逻辑，别人的程序比我快 - 从SPSC queue谈起]]></title><link>https://blog.youkuaiyun.com/Max_Cong/article/details/116881411</link><guid>https://blog.youkuaiyun.com/Max_Cong/article/details/116881411</guid><author>Max_Cong</author><pubDate>Sun, 16 May 2021 08:51:37 +0800</pubDate><description><![CDATA[关注公众号获取更多信息：





最近也写了很多关于内存模型的文章，会有人有灵魂一问 -- 内存模型到底有啥用？什么时候能用到内存模型？这个问题我也思考了很久，接下来我会举个在现实中的应用 -- SPSC queue。



有些人会说，SPSC queue？我分分钟就能给你写出一个。很简单，就是普通的queue加上锁就行了。但是既然我们都说过了内存模型，我们就要忘记锁这个东西。的确，锁是解决很多线程问题的”万金油“，可是有没有想过，锁的应用，给你的系统带来了多大的额外开销。之前曾经维护过公司的一个软..]]></description><category></category></item><item><title><![CDATA[走进C++11（四十二）释放消费顺序/序列一致顺序 内存模型（五）]]></title><link>https://blog.youkuaiyun.com/Max_Cong/article/details/116881311</link><guid>https://blog.youkuaiyun.com/Max_Cong/article/details/116881311</guid><author>Max_Cong</author><pubDate>Sun, 16 May 2021 08:48:16 +0800</pubDate><description><![CDATA[关注公众号获取更多信息：



释放消费顺序



若线程 A 中的原子存储带标签 memory_order_release 而线程 B 中来自同一对象的读取存储值的原子加载带标签 memory_order_consume ，则线程 A 视角中先发生于原子存储的所有内存写入（非原子和宽松原子的），会在线程 B 中该加载操作所携带依赖进入的操作中变成可见副效应，即一旦完成原子加载，则保证线程B中，使用从该加载获得的值的运算符和函数，能见到线程 A 写入内存的内容。



同步仅在释放和消费同一原子对象的线..]]></description><category></category></item><item><title><![CDATA[走进C++11（四十一）释放获得顺序 内存模型（四）]]></title><link>https://blog.youkuaiyun.com/Max_Cong/article/details/116881265</link><guid>https://blog.youkuaiyun.com/Max_Cong/article/details/116881265</guid><author>Max_Cong</author><pubDate>Sun, 16 May 2021 08:45:54 +0800</pubDate><description><![CDATA[关注公众号获取更多信息：



若线程 A 中的一个原子存储带标签memory_order_release，而线程 B 中来自同一变量的原子加载带标签memory_order_acquire，则从线程 A 的视角先发生于原子存储的所有内存写入（非原子及宽松原子的），在线程 B 中成为可见副效应，即一旦原子加载完成，则保证线程 B 能观察到线程 A 写入内存的所有内容。



同步仅建立在释放和获得同一原子对象的线程之间。其他线程可能看到与被同步线程的一者或两者相异的内存访问顺序。



在强顺序...]]></description><category></category></item><item><title><![CDATA[走进C++11（四十）最宽松的顺序 memory_order_relaxed 内存模型（三）]]></title><link>https://blog.youkuaiyun.com/Max_Cong/article/details/116881203</link><guid>https://blog.youkuaiyun.com/Max_Cong/article/details/116881203</guid><author>Max_Cong</author><pubDate>Sun, 16 May 2021 08:43:10 +0800</pubDate><description><![CDATA[关注公众号获取更多信息：





之前讲的都是理论相关的，下面详细讲一下我们现实中会使用到的内存模型。今天是最简单也是最宽松的内存模型----memory_order_relaxed



带标签 memory_order_relaxed 的原子操作无同步操作；它们不会在同时的内存访问间强加顺序。它们只保证原子性和修改顺序一致性。

例如，




对于最初为零的 x 和 y ，// 线程 1 ：r1 = y.load(std::memory_order_relaxed); // Ax.store...]]></description><category></category></item><item><title><![CDATA[走进C++11（三十九） 内存模型（二）]]></title><link>https://blog.youkuaiyun.com/Max_Cong/article/details/116880934</link><guid>https://blog.youkuaiyun.com/Max_Cong/article/details/116880934</guid><author>Max_Cong</author><pubDate>Sun, 16 May 2021 08:41:44 +0800</pubDate><description><![CDATA[关注公众号获取更多信息：





今天继续聊内存模型。



上篇文章讲了一些概念。今天讲一些小细节，为最后的总结做铺垫。











上图所示的是一个典型的多核CPU系统架构，它包含有2个CPU核，每个CPU核有一个私有的32KB 的 L1 cache，两个CPU 核共享 1MB的 L2 cache 以及 512MB的主存。



在这个内存模型下，cpu写数据并不是立即写入RAM中，而是写入L1 cache，再从L1 cache存入(store) RAM中，读数据也是先从L1 ...]]></description><category></category></item><item><title><![CDATA[走进C++11（三十八） 内存模型（一）]]></title><link>https://blog.youkuaiyun.com/Max_Cong/article/details/116880851</link><guid>https://blog.youkuaiyun.com/Max_Cong/article/details/116880851</guid><author>Max_Cong</author><pubDate>Sun, 16 May 2021 08:29:02 +0800</pubDate><description><![CDATA[关注公众号获取更多信息：





上一篇文章讲atomic的时候，曾经涉及到内存模型，atomic的默认类型是：memory_order_seq_cst。这个东东是啥？



其实它是内存模型的一种。下面我们来详细讲解一下C++11内存模型，读完这篇文章，你就能弄懂它的意思了。注意，这篇文章可能偏理论性质，也不会有例子，如果想快速入门可以直接看下一篇文章。



1. 内存模型的所有种类：



typedefenummemory_order{    memory_order_relaxed...]]></description><category></category></item><item><title><![CDATA[走进C++11（三十七）原子操作之 std::atomic]]></title><link>https://blog.youkuaiyun.com/Max_Cong/article/details/116880786</link><guid>https://blog.youkuaiyun.com/Max_Cong/article/details/116880786</guid><author>Max_Cong</author><pubDate>Sun, 16 May 2021 08:27:28 +0800</pubDate><description><![CDATA[关注公众号获取更多信息：







C++11提供了一个原子类型std::atomic&lt;T&gt;，可以使用任意类型作为模板参数，C++11内置了整型的原子变量，可以方便的使用原子变量，使用原子变量就不用互斥变量来保护该变量了。



每个 std::atomic 模板的实例化和全特化定义一个原子类型。若一个线程写入原子对象，同时另一线程从它读取，则行为良好定义（数据竞争的细节我们会在下节--内存模型里讲解）



另外，对原子对象的访问可以建立线程间同步，并按 std::mem...]]></description><category></category></item><item><title><![CDATA[走进C++11（三十六） 字符串字面量]]></title><link>https://blog.youkuaiyun.com/Max_Cong/article/details/112599116</link><guid>https://blog.youkuaiyun.com/Max_Cong/article/details/112599116</guid><author>Max_Cong</author><pubDate>Thu, 14 Jan 2021 08:51:03 +0800</pubDate><description><![CDATA[关注公众号获取更多信息：





字符串字面量可能经常会在工作中用到，特别是写UT的时候。



想象一下如下场景：



一个程序，我们想要输入如下的内容：




std::string normal_str = "First line.\nSecond line.\nEnd of message.\n";



为何换行，我们必须要用\n再表示，同时考虑下边的场景：



我们要打印如下内容：




thisis"test"



我们不得不用如下的代码，对"进行转义：

...]]></description><category></category></item><item><title><![CDATA[走进C++11（三十五）weak_ptr]]></title><link>https://blog.youkuaiyun.com/Max_Cong/article/details/112599098</link><guid>https://blog.youkuaiyun.com/Max_Cong/article/details/112599098</guid><author>Max_Cong</author><pubDate>Thu, 14 Jan 2021 08:48:47 +0800</pubDate><description><![CDATA[关注公众号获取更多信息：





开始之前先看一段代码，


struct A {std::shared_ptr&lt;B&gt;pointer;~A(){std::cout&lt;&lt; "A被销毁"&lt;&lt;std::end;}};struct B {std::shared_ptr&lt;A&gt;pointer;~B(){std::cout&lt;&lt; "B被销毁"&lt;&lt;std::end;}};int main() {auto a =std::make_shared&lt;A.]]></description><category></category></item><item><title><![CDATA[走进C++11（三十四）unique_ptr]]></title><link>https://blog.youkuaiyun.com/Max_Cong/article/details/112599079</link><guid>https://blog.youkuaiyun.com/Max_Cong/article/details/112599079</guid><author>Max_Cong</author><pubDate>Thu, 14 Jan 2021 08:47:35 +0800</pubDate><description><![CDATA[关注公众号获取更多信息：







std::unique_ptr是C++11标准中用来取代std::auto_ptr的指针容器(在C++11中，auto_ptr被废弃)。它不能与其它unique_ptr类型的指针对象共享所指对象的内存。这种”所有权”仅能够通过标准库的move函数来转移。unique_ptr是一个删除了拷贝构造函数、保留了移动构造函数的指针封装类型。下面的脑图总结了unique_ptr的特性：







1. 一个unique_ptr"拥有"它所指向的对象。与shared...]]></description><category></category></item><item><title><![CDATA[走进C++11（三十三）shared_ptr]]></title><link>https://blog.youkuaiyun.com/Max_Cong/article/details/112599069</link><guid>https://blog.youkuaiyun.com/Max_Cong/article/details/112599069</guid><author>Max_Cong</author><pubDate>Thu, 14 Jan 2021 08:46:09 +0800</pubDate><description><![CDATA[关注公众号获取更多信息：





shared_ptr实现共享式拥有概念。多个智能指针可以指向相同对象，该对象和其相关资源会在“最后一个引用被销毁”时候释放。从名字share就可以看出了资源可以被多个指针共享，它使用计数机制来表明资源被几个指针共享。可以通过成员函数use_count()来查看资源的所有者个数。除了可以通过new来构造，还可以通过传入auto_ptr, unique_ptr,weak_ptr来构造。当我们调用release()时，当前指针会释放资源所有权，计数减一。当计数等于0时，资源会.]]></description><category></category></item><item><title><![CDATA[走进C++11（三十二） 智能指针系列 总览]]></title><link>https://blog.youkuaiyun.com/Max_Cong/article/details/112599059</link><guid>https://blog.youkuaiyun.com/Max_Cong/article/details/112599059</guid><author>Max_Cong</author><pubDate>Thu, 14 Jan 2021 08:44:43 +0800</pubDate><description><![CDATA[关注公众号获取更多信息：





智能指针可以说是C++11引入的关于内存的最令人期待的特性。



所谓存在即合理，那么为什么要引入智能指针呢？



C/C++程序员在搬砖的过程中，难免会与内存打交道。在C++11前，可能是new/delete或者C的malloc()/free()。指针用起来，真是一直用一直爽，你赋值给我，我赋值给你，到最后要不是忘记释放内存，要不就是一个人释放内存，别人都不知道，别人不知道要不就是访问了不该访问的内容，更有甚者会再次释放这个内存。刚才说的就是内存常见的三种错误...]]></description><category></category></item><item><title><![CDATA[走进C++11（三十一） 如何用60行实现C++11 thread pool]]></title><link>https://blog.youkuaiyun.com/Max_Cong/article/details/112599043</link><guid>https://blog.youkuaiyun.com/Max_Cong/article/details/112599043</guid><author>Max_Cong</author><pubDate>Thu, 14 Jan 2021 08:43:52 +0800</pubDate><description><![CDATA[关注公众号获取更多信息：





开始之前先上一下代码链接：



https://github.com/maxcong001/threadPool



最近看了看我的计划，写道这里也算是到了一半，大部分都是讲的单一的C++11的用法，基本都是理论知识，就像我上大学的时候，老师一直讲理论知识，结局就是能去能不去的时候，我选择了后者。所以在这里穿插一下小的综合运用文章，让大家知道为什么要用C++11，C++11好在哪里，项目中如何运用C++11.



首先介绍一下背景。在我们的工作中，避免不了多...]]></description><category></category></item><item><title><![CDATA[走进C++11（三十）标准化条件变量 -- condition_variable]]></title><link>https://blog.youkuaiyun.com/Max_Cong/article/details/112599022</link><guid>https://blog.youkuaiyun.com/Max_Cong/article/details/112599022</guid><author>Max_Cong</author><pubDate>Thu, 14 Jan 2021 08:41:56 +0800</pubDate><description><![CDATA[这篇文章是有关线程与并发的最后一篇文章，随后会综合之前讲的，完成一个小例子：如何用几十行代码实现一个线程池。



std::condition_variable是条件变。Linux下使用 Pthread库中的 pthread_cond_*()函数提供了与条件变量相关的功能。和pthread_cond_*()一样，我们可以使用条件变量（condition_variable）实现多个线程间的同步操作；当条件不满足时，相关线程被一直阻塞，直到某种条件出现，这些线程才会被唤醒。C++11通过std::co...]]></description><category></category></item><item><title><![CDATA[boost log -- header only 的心酸历程(五) 优化]]></title><link>https://blog.youkuaiyun.com/Max_Cong/article/details/112002493</link><guid>https://blog.youkuaiyun.com/Max_Cong/article/details/112002493</guid><author>Max_Cong</author><pubDate>Thu, 31 Dec 2020 09:34:57 +0800</pubDate><description><![CDATA[之前写过这个boost log的系列，实现了一个小的工程，这样可以拿去用。

最近看这个工程，发现有个地方可以优化。



每次我们去调用__LOG的时候，我们都会去组装这个message。



      tostringstream var;                                                    \
      var &lt;&lt; "[" &lt;&lt; __FILE__ &lt;&lt; ":" &lt;&lt; __LINE__ &lt;..]]></description><category></category></item><item><title><![CDATA[走进C++11（二十九） 将工作打包成任务，丢给执行者 -- std::packaged_task]]></title><link>https://blog.youkuaiyun.com/Max_Cong/article/details/111880899</link><guid>https://blog.youkuaiyun.com/Max_Cong/article/details/111880899</guid><author>Max_Cong</author><pubDate>Tue, 29 Dec 2020 10:00:10 +0800</pubDate><description><![CDATA[其实std::packaged_task并没有引入新的概念， 它是一个包装类，它包装任何可调用 (Callable) 目标（函数、 lambda 表达式、 bind 表达式或其他函数对象），使得能异步调用它。其返回值或所抛异常被存储于能通过 std::future 对象访问的共享状态中。



正如 std::function ， std::packaged_task 是多态、具分配器的容器：可在堆上或以提供的分配器分配存储的可调用对象。



std::packaged_task本身很简...]]></description><category></category></item><item><title><![CDATA[走进C++11（二十八） 一诺千金 std::promise]]></title><link>https://blog.youkuaiyun.com/Max_Cong/article/details/111880888</link><guid>https://blog.youkuaiyun.com/Max_Cong/article/details/111880888</guid><author>Max_Cong</author><pubDate>Tue, 29 Dec 2020 09:59:32 +0800</pubDate><description><![CDATA[promise 对象可以保存某一类型 T 的值，该值可被 future 对象读取（可能在另外一个线程中），因此 promise 也提供了一种线程同步的手段。在 promise 对象构造时可以和一个共享状态（通常是std::future）相关联，并可以在相关联的共享状态(std::future)上保存一个类型为 T 的值。



可以通过 get_future 来获取与该 promise 对象相关联的 future 对象，调用该函数之后，两个对象共享相同的共享状态(shared state)

...]]></description><category></category></item></channel></rss>