- 博客(153)
- 收藏
- 关注
原创 走进C++11(四十六)inline namespace
关注公众号获取更多信息:这篇文章是这个系列的最后一篇。这个系列是我第一次尝试写一个系列的文章。其中发现了很多不足的地方。回首之前的文章,在排版,内容形式等方面都很欠缺。之后我会努力呈现更好的内容。敬请期待。最后的一篇留给了inline namespace。说起inline namespace不得不先说一下namespace, namespace最常用的就是C++标准的std名字空间。名字空间的作用是区别同名的全局成员,例如在两个头文件中声明了同名的函数,如果在其他地方同时包含了两个头..
2021-05-16 08:55:18
1032
1
原创 走进C++11(四十五) thread_local
关注公众号获取更多信息:今天说说thread_local 关键字。说到thread_local就要说到C++存储类说明符。C++有如下几种存储类说明符:auto 自动存储期(C++11前) register 自动存储期,另提示编译器将此对象置于处理器的寄存器。(弃用)(C++17前) static 静态或线程存储期和内部连接。 extern 静态或线程存储期和外部连接。 thread_local 线程存储期 mutabl...
2021-05-16 08:53:53
532
原创 走进C++11(四十四) noexcept
关注公众号获取更多信息:好久没有没有更新文章了,因为最近忙于A,B,C.....好吧我摊牌了。就是因为懒。这个文章是这个系列的倒数第三篇文章。C++11系列更新完了之后,我会更新其他编程相关的文章。言归正传,今天讲的是noexcept。这个关键字也是属于你不知道它也能编出好程序的,没有存在感的一个关键字,但是用好它会让你的程序更加清晰,它会告诉编译器,这个函数不可能抛出异常,这样编译器对你的程序做更多的优化。由于C++中的异常处理是在运行时而不是编译时检测的。为了实现运行时检测...
2021-05-16 08:52:45
507
原创 走进C++11(四十三)memory order 番外篇一 为什么实现同样逻辑,别人的程序比我快 - 从SPSC queue谈起
关注公众号获取更多信息:最近也写了很多关于内存模型的文章,会有人有灵魂一问 -- 内存模型到底有啥用?什么时候能用到内存模型?这个问题我也思考了很久,接下来我会举个在现实中的应用 -- SPSC queue。有些人会说,SPSC queue?我分分钟就能给你写出一个。很简单,就是普通的queue加上锁就行了。但是既然我们都说过了内存模型,我们就要忘记锁这个东西。的确,锁是解决很多线程问题的”万金油“,可是有没有想过,锁的应用,给你的系统带来了多大的额外开销。之前曾经维护过公司的一个软..
2021-05-16 08:51:37
760
2
原创 走进C++11(四十二)释放消费顺序/序列一致顺序 内存模型(五)
关注公众号获取更多信息:释放消费顺序若线程 A 中的原子存储带标签 memory_order_release 而线程 B 中来自同一对象的读取存储值的原子加载带标签 memory_order_consume ,则线程 A 视角中先发生于原子存储的所有内存写入(非原子和宽松原子的),会在线程 B 中该加载操作所携带依赖进入的操作中变成可见副效应,即一旦完成原子加载,则保证线程B中,使用从该加载获得的值的运算符和函数,能见到线程 A 写入内存的内容。同步仅在释放和消费同一原子对象的线..
2021-05-16 08:48:16
450
原创 走进C++11(四十一)释放获得顺序 内存模型(四)
关注公众号获取更多信息:若线程 A 中的一个原子存储带标签memory_order_release,而线程 B 中来自同一变量的原子加载带标签memory_order_acquire,则从线程 A 的视角先发生于原子存储的所有内存写入(非原子及宽松原子的),在线程 B 中成为可见副效应,即一旦原子加载完成,则保证线程 B 能观察到线程 A 写入内存的所有内容。同步仅建立在释放和获得同一原子对象的线程之间。其他线程可能看到与被同步线程的一者或两者相异的内存访问顺序。在强顺序...
2021-05-16 08:45:54
300
原创 走进C++11(四十)最宽松的顺序 memory_order_relaxed 内存模型(三)
关注公众号获取更多信息:之前讲的都是理论相关的,下面详细讲一下我们现实中会使用到的内存模型。今天是最简单也是最宽松的内存模型----memory_order_relaxed带标签 memory_order_relaxed 的原子操作无同步操作;它们不会在同时的内存访问间强加顺序。它们只保证原子性和修改顺序一致性。例如,对于最初为零的 x 和 y ,// 线程 1 :r1 = y.load(std::memory_order_relaxed); // Ax.store...
2021-05-16 08:43:10
4303
3
原创 走进C++11(三十九) 内存模型(二)
关注公众号获取更多信息:今天继续聊内存模型。上篇文章讲了一些概念。今天讲一些小细节,为最后的总结做铺垫。上图所示的是一个典型的多核CPU系统架构,它包含有2个CPU核,每个CPU核有一个私有的32KB 的 L1 cache,两个CPU 核共享 1MB的 L2 cache 以及 512MB的主存。在这个内存模型下,cpu写数据并不是立即写入RAM中,而是写入L1 cache,再从L1 cache存入(store) RAM中,读数据也是先从L1 ...
2021-05-16 08:41:44
407
原创 走进C++11(三十八) 内存模型(一)
关注公众号获取更多信息:上一篇文章讲atomic的时候,曾经涉及到内存模型,atomic的默认类型是:memory_order_seq_cst。这个东东是啥?其实它是内存模型的一种。下面我们来详细讲解一下C++11内存模型,读完这篇文章,你就能弄懂它的意思了。注意,这篇文章可能偏理论性质,也不会有例子,如果想快速入门可以直接看下一篇文章。1. 内存模型的所有种类:typedefenummemory_order{ memory_order_relaxed...
2021-05-16 08:29:02
638
原创 走进C++11(三十七)原子操作之 std::atomic
关注公众号获取更多信息:C++11提供了一个原子类型std::atomic<T>,可以使用任意类型作为模板参数,C++11内置了整型的原子变量,可以方便的使用原子变量,使用原子变量就不用互斥变量来保护该变量了。每个 std::atomic 模板的实例化和全特化定义一个原子类型。若一个线程写入原子对象,同时另一线程从它读取,则行为良好定义(数据竞争的细节我们会在下节--内存模型里讲解)另外,对原子对象的访问可以建立线程间同步,并按 std::mem...
2021-05-16 08:27:28
2276
原创 走进C++11(三十六) 字符串字面量
关注公众号获取更多信息:字符串字面量可能经常会在工作中用到,特别是写UT的时候。想象一下如下场景:一个程序,我们想要输入如下的内容:std::string normal_str = "First line.\nSecond line.\nEnd of message.\n";为何换行,我们必须要用\n再表示,同时考虑下边的场景:我们要打印如下内容:thisis"test"我们不得不用如下的代码,对"进行转义:...
2021-01-14 08:51:03
1594
原创 走进C++11(三十五)weak_ptr
关注公众号获取更多信息:开始之前先看一段代码,struct A {std::shared_ptr<B>pointer;~A(){std::cout<< "A被销毁"<<std::end;}};struct B {std::shared_ptr<A>pointer;~B(){std::cout<< "B被销毁"<<std::end;}};int main() {auto a =std::make_shared<A.
2021-01-14 08:48:47
326
原创 走进C++11(三十四)unique_ptr
关注公众号获取更多信息:std::unique_ptr是C++11标准中用来取代std::auto_ptr的指针容器(在C++11中,auto_ptr被废弃)。它不能与其它unique_ptr类型的指针对象共享所指对象的内存。这种”所有权”仅能够通过标准库的move函数来转移。unique_ptr是一个删除了拷贝构造函数、保留了移动构造函数的指针封装类型。下面的脑图总结了unique_ptr的特性:1. 一个unique_ptr"拥有"它所指向的对象。与shared...
2021-01-14 08:47:35
427
原创 走进C++11(三十三)shared_ptr
关注公众号获取更多信息:shared_ptr实现共享式拥有概念。多个智能指针可以指向相同对象,该对象和其相关资源会在“最后一个引用被销毁”时候释放。从名字share就可以看出了资源可以被多个指针共享,它使用计数机制来表明资源被几个指针共享。可以通过成员函数use_count()来查看资源的所有者个数。除了可以通过new来构造,还可以通过传入auto_ptr, unique_ptr,weak_ptr来构造。当我们调用release()时,当前指针会释放资源所有权,计数减一。当计数等于0时,资源会.
2021-01-14 08:46:09
942
原创 走进C++11(三十二) 智能指针系列 总览
关注公众号获取更多信息:智能指针可以说是C++11引入的关于内存的最令人期待的特性。所谓存在即合理,那么为什么要引入智能指针呢?C/C++程序员在搬砖的过程中,难免会与内存打交道。在C++11前,可能是new/delete或者C的malloc()/free()。指针用起来,真是一直用一直爽,你赋值给我,我赋值给你,到最后要不是忘记释放内存,要不就是一个人释放内存,别人都不知道,别人不知道要不就是访问了不该访问的内容,更有甚者会再次释放这个内存。刚才说的就是内存常见的三种错误...
2021-01-14 08:44:43
251
原创 走进C++11(三十一) 如何用60行实现C++11 thread pool
关注公众号获取更多信息:开始之前先上一下代码链接:https://github.com/maxcong001/threadPool最近看了看我的计划,写道这里也算是到了一半,大部分都是讲的单一的C++11的用法,基本都是理论知识,就像我上大学的时候,老师一直讲理论知识,结局就是能去能不去的时候,我选择了后者。所以在这里穿插一下小的综合运用文章,让大家知道为什么要用C++11,C++11好在哪里,项目中如何运用C++11.首先介绍一下背景。在我们的工作中,避免不了多...
2021-01-14 08:43:52
953
原创 走进C++11(三十)标准化条件变量 -- condition_variable
这篇文章是有关线程与并发的最后一篇文章,随后会综合之前讲的,完成一个小例子:如何用几十行代码实现一个线程池。std::condition_variable是条件变。Linux下使用 Pthread库中的 pthread_cond_*()函数提供了与条件变量相关的功能。和pthread_cond_*()一样,我们可以使用条件变量(condition_variable)实现多个线程间的同步操作;当条件不满足时,相关线程被一直阻塞,直到某种条件出现,这些线程才会被唤醒。C++11通过std::co...
2021-01-14 08:41:56
343
原创 boost log -- header only 的心酸历程(五) 优化
之前写过这个boost log的系列,实现了一个小的工程,这样可以拿去用。最近看这个工程,发现有个地方可以优化。每次我们去调用__LOG的时候,我们都会去组装这个message。 tostringstream var; \ var << "[" << __FILE__ << ":" << __LINE__ <..
2020-12-31 09:34:57
485
原创 走进C++11(二十九) 将工作打包成任务,丢给执行者 -- std::packaged_task
其实std::packaged_task并没有引入新的概念, 它是一个包装类,它包装任何可调用 (Callable) 目标(函数、 lambda 表达式、 bind 表达式或其他函数对象),使得能异步调用它。其返回值或所抛异常被存储于能通过 std::future 对象访问的共享状态中。正如 std::function , std::packaged_task 是多态、具分配器的容器:可在堆上或以提供的分配器分配存储的可调用对象。std::packaged_task本身很简...
2020-12-29 10:00:10
362
原创 走进C++11(二十八) 一诺千金 std::promise
promise 对象可以保存某一类型 T 的值,该值可被 future 对象读取(可能在另外一个线程中),因此 promise 也提供了一种线程同步的手段。在 promise 对象构造时可以和一个共享状态(通常是std::future)相关联,并可以在相关联的共享状态(std::future)上保存一个类型为 T 的值。可以通过 get_future 来获取与该 promise 对象相关联的 future 对象,调用该函数之后,两个对象共享相同的共享状态(shared state)...
2020-12-29 09:59:32
396
原创 走进C++11(二十七) 处理未来发生的事情 std::future
这一节可能是C++11最难说明白的一节。其实future有两个兄弟,一个是std::future, 一个是它大哥std::shared_future。他们的区别就是std::future只支持移动语义,它所引用的共享状态不与另一异步返回对象共享。换成人话就是如果你想再多个线程共享一个future,那么你应该用std::shared_future,换成大白话就是你要是想多个线程等待一个future,那么你应该用std::shared_future。如果还是不明白,文章最后会给一个小例子说明...
2020-12-29 09:58:55
527
1
原创 走进C++11(二十六) RAII风格锁std::lock_guard/std::unique_lock
今天聊聊std::lock_guard/std::unique_lock,首先要说的是unique_lock 是 lock_guard 的升级加强版,它具有 lock_guard 的所有功能,同时又具有其他很多方法,使用起来更强灵活方便,能够应对更复杂的锁定需要。平时也会使用到std::lock_guard,但是std::unique_lock用的比较少。因为std::lock_guard可以满足我们大部分需求。还有一个关键的问题,我们已经有了std::mutex,为什么还要存在这两个东...
2020-12-29 09:58:04
1484
2
原创 走进C++11(二十五)一统江湖之mutex -- std::mutex
Mutex 又称互斥量,C++ 11中与 Mutex 相关的类(包括锁类型)和函数都声明在<mutex>头文件中,所以如果你需要使用 std::mutex,就必须包含<mutex>头文件。C++11中新增了<mutex>,它是C++标准程序库中的一个头文件,定义了C++11标准中的一些互斥访问的类与方法等。C++11标准库定义了4个互斥类:std::mutexstd::mutex 是C++11 中最基本的互斥量,...
2020-12-29 09:57:11
408
1
原创 走进C++11(二十四)一统江湖之线程 -- std::thread
文成武德、泽被苍生,千秋万载,一统江湖至此,是不是发现了,C++11的很多新特性都是为了“一统江湖”,包括之前讲过的std::function等。为什么要包装thread呢?pthread它不香么?std::thread 简介众所周知,现在操作系统分两大阵营,当然还包括一些小众的系统,不同的系统对thread的支持略有不同,比如你再windows系统上就要用CreateThread 来创建一个线程,同样一份代码,要想移植要花很大力气。当然如果代码写的好,用一个抽...
2020-12-29 09:55:45
416
原创 走进C++11(二十三) 函数对象包装器之std::function
std::function 是C++11中又一个新的概念。想想在之前的C++中,function一直是一个尴尬的存在,它作为程序的一部分,被“钉死”在程序的代码段,而且可调用的对象五花八门。C++11打破了这个尴尬,统一可调用对象的概念,可调用对象有以下几种定义: 是一个函数指针,参考 C++ 函数指针和函数类型; 是一个具有operator()成员函数的类的对象; 可被转换成函数指针的类对象; 一个类成员函数指针; C++中可调用...
2020-12-29 09:54:56
330
原创 走进C++11(二十二) 之lambda(匿名函数)
提示这篇文章可能较长,分为如下几部分 什么是lambda函数 Lambda函数的用处 Lambda函数中的变量截取 Lambda函数和STL 1. 什么是lambda函数lambda表达式无疑是C++11最激动人心的特性之一!它会使你编写的代码变得更优雅、更快速! 它实现了C++11对于支持闭包的支持。首先我们先看一下什么叫做闭包维基百科上,对于闭包的解释是:In programming languages, a clos...
2020-12-29 09:54:04
366
原创 走进C++11(二十一)移动语义、完美转发
上文讲了什么是右值引用。右值引用(rvalue reference)是 C++11 为了实现移动语意(move semantic)和完美转发(perfect forwarding)而提出来的。右值引用,简单说就是绑定在右值上的引用。右值的内容可以直接移动(move)给左值对象,而不需要进行开销较大的深拷贝(deep copy)。在面向对象中,有的类是可以拷贝的,例如车、房等他们的属性是可以复制的,可以调用拷贝构造函数,有点类的对象则是独一无二的,或者类的资源是独一无二的,...
2020-12-29 09:52:37
347
原创 走进C++11(二十) -- 左值、右值、左值引用、右值引用
这里主要讲讲左值/纯右值/将亡值的概念。以后会讲如何应用。左值(lvalue,left value),顾名思义就是赋值符号左边的值。准确来说,左值是表达式(不一定是赋值表达式)后依然存在的持久对象。右值(rvalue,right value),右边的值,是指表达式结束后就不再存在的临时对象。而 C++11中为了引入强大的右值引用,将右值的概念进行了进一步的划分,分为:纯右值、将亡值。纯右值(prvalue,pure rvalue),纯粹的右值,要么是纯粹的字面量,...
2020-12-29 09:49:02
439
1
原创 走进C++11(十九) 开篇预告--语言运行期强化系列
前几篇文章讲了一下语言可用性强化,也就是编写代码或编译器编译代码时的强化。下边讲一下语言运行期强化。其中最主要的就是下边几个方面: 关注公众号获取更多信息: /** * 頂頂頂頂頂頂頂頂頂 頂頂頂頂頂頂頂頂頂 * 頂頂頂頂頂頂頂 頂頂 * 頂頂 頂頂頂頂頂頂頂頂頂頂頂 * 頂頂 頂頂頂頂頂頂頂頂頂頂頂 * 頂頂 頂頂 頂頂 * 頂頂 頂頂 頂頂頂 頂頂 * 頂頂 頂...
2020-11-22 17:15:42
193
原创 走进C++ (十八) range based for
熟悉C#或者python的人都知道在C#和python中存在一种for的使用方法不需要明确给出容器的开始和结束条件,就可以遍历整个容器。C++11吸取了他们的优点,引入了这种方法也就是基于范围的For(Range-Based-For)。值得一说的是,如果没有range-based-for,我们还是可以遍历容器的。它是对for的扩展。比如C98时候我们可以这样:int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };for (i...
2020-11-22 17:14:23
915
原创 走进C++11(十七) >
是的你没看错,今天的题目就是 >。这。。。。。。有啥好讲的?其实经常用模板的人可能一不小心都吃过这个亏。对于C++程序员来说,>>是位右移操作符,但在一此应用中会涉及到需要连写的情景,例如:模板和表达式转换。在实例化模板时会出现连续两个右尖括号,同样static_cast、dynamic_cast、reinterpret_cast、const_cast表达式转换时也会遇到相同的情况。C++98标准是让程序员在>>之间填上一个空格,而C+...
2020-11-22 17:11:09
255
原创 走进C++11(十六)外部模板
关键词extern语法externtemplateclass|struct模板名<实参列表>;解释类模板自身并不是类型、对象或任何其他实体。不会从从仅含模板定义的源文件生成任何代码。必须实例化模板以令任何代码出现:必须提供模板实参,使得编译器能生成实际的类(或从函数模板生成函数)。如果外部模板声明出现于某个编译单元中,那么与之对应的显式实例化必须出现于另一个编译单元中或者同一个编译单元的后续代码中;...
2020-11-22 17:09:21
528
原创 走进C++11(十五)using(别名)替代typedef
关键字using语法别名声明是具有下列语法的声明:using标识符attr(可选)=类型标识;(1)template<模板形参列表>using标识符attr(可选)=类型标识;(2)attr(C++11)-可选的任意数量属性的序列标识符-此声明引入的名字,它成为一个类型名(1)或一个模板名(2)模板形参列表-模板形参列表,同模板声明类型标识...
2020-11-22 17:07:51
525
原创 走进C++11(十四)变长参数模板
解释C++03只有固定模板参数。C++11 加入新的表示法,允许任意个数、任意类别的模板参数,不必在定义时将参数的个数固定。变长模板、变长参数是依靠C++11新引入的参数包的机制实现的。参数包 一个模板形参包(template parameter pack)是一个接受零个或多个模板实参的模板形参。 template<class...Types>structTuple{};Tuple<> t0; // T...
2020-11-22 17:05:50
776
原创 走进C++11(十三) 变量之 -- 结构化绑定
其实C++11结构化绑定做的并不好,想要用结构化绑定的更好的版本要等到C++17。所以这里会提到C++17的用法。简介C++17语言上(语言特性,而不是标准库新特性)引入了一种结构化绑定的新特性,使用该特性可以利用auto同时声明多个不同类型的变量并即时从一个tuple-like对象得到赋值/初始化。Structured binding不但可以使C++的代码更加简洁,而且似乎从语法上更贴近Python这种脚本语言了。另外,auto变量会在编译时推导出变量的类型,所以无需担心会...
2020-11-22 17:04:11
1250
原创 走进C++11(十二)变量之--(变长)列表初始化
本文是一篇C++11关于变量的改进关键词std::initializer_list解释在 C++98/03 中的对象初始化方法有很多种,这无疑增大了学习难度。这中情况在C++11中终于得到解决。先看看没有C++11的时候 //初始化列表 int i_arr[3] = { 1, 2, 3 }; //普通数组 struct A { int x; struct B { ...
2020-11-22 17:02:30
642
原创 走进C++11(十一) nullptr/nullptr_t
解释关键词 nullptr 代表指针字面量。它是 std::nullptr_t 类型的纯右值。存在从 nullptr 到任何指针类型及任何成员指针类型的隐式转换。同样的转换对于任何空指针常量也存在,空指针常量包括 std::nullptr_t 的值,以及宏 NULL。引入原因为什么引入nullptr呢, 不是有NULL这个关键字么?的却,但是我想问你NULL是什么类型的?C++98中NULL是个宏定义,明确规定NULL是个整型0值:/*...
2020-11-21 16:50:38
739
原创 走进C++11(十) constexpr
关键词constexpr解释constexpr 说明符能应用到变量或函数声明。对于变量,它声明该变量必须在编译时求值。对于函数,编译时求值是可能的。constexpr 变量和函数(若给定了合适的函数实参)即可用于仅允许编译时常量表达式之处。constexpr 变量必须满足下列要求: 其类型必须是字面类型 (LiteralType)。 它必须被立即初始化 其初始化的全表达式,包括所有隐式转换、构造函数调用等,都必...
2020-11-21 16:49:07
387
原创 走进C++11(九) 类型推导之 auto
关键字auto语法(1) (C++11起) decltype(auto)(2) (C++14 起) 类型制约 auto(3) (C++20起) 类型制约 decltype(auto)(4) (C++20起) 类型制约 - 概念名,可以有限定,可以后随<>包围的模板实参列表 1,3)用模板实参推导的规则推导类型。2,4)类型为 decltype(expr),其中 expr 是初始化器。占位符 auto 可伴随如 const 或...
2020-11-21 16:47:56
301
原创 走进C++11(八) 返回类型推导 decltype
关键词decltype语法decltype(实体)(1)(C++11起)decltype(表达式)(2)(C++11起)解释1)若实参是指名某个结构化绑定的无括号的标识表达式,则 decltype 产生被引用类型(在关于结构化绑定声明的说明中有所描述)。(C++17起)2)若实参是指名某个非类型模板形参的无括号的标识表达式,则 decltype 生成该模板形参的类型(当该模板形参以占位符类型声明时...
2020-11-21 16:46:01
908
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人