C++中的位域以及实现一个抽象位域类

March 17, 2017 at 11:52 am

这里说的位域(bit-field)是C/C++语言中的一个概念,它用来为struct/class/union中的成员指定特定的以位为单位的尺寸。之所以要写这个,是因为今天看到了一个位域类的实现,这个类似乎能更方便的使用位域,那就看看它到底如何实现的,顺道把位域复习一遍。说实话在实际项目中没有写过位域,一方面除了C/C++语言,一般的语言都没有这个特性;另一方面,位域在一般的项目中使用较少,仅会出现在偏底层的一些代码中。似乎偶尔在面试中会有关于位域的题目,有段时间学习过一下,不过现在也基本上忘光了,博客也好久没更了,暂时就先补上这一篇。 本文主要有如下几个内容: 1. 位域的基本概念 2. 位域内存占用和pack 3. 实现一个抽象位域类 位域的基本概念 位域通常用于代替一些位操作,典型的使用场景比如占1至2个比特的标记位,如果直接使用bool来定义这个标记位,将会浪费内存空间,32个只有true/false的标记位使用位域只需要4字节,而如果全部定义为bool则需要32个字节;一个典型的方法是将这32个标记位用一个32位的整数表示,每个标记位通过对这个整数的位操作来代替,从功能上来说,位域只是对于代码编写者(阅读者)而言比位操作更加直观一点的方式,通常来讲CPU并没有对特定位进行操作的指令,所以位域操作最终仍会被编译器转化为底层的位操作指令。 如果不需要考虑到内存空间的浪费,或者已经习惯对数字的位操作,那么位域并不是必须的。 下面给出一个最简单的位域的例子(例子引用自 http://en.cppreference.com/w/cpp/language/bit_field): #include <iostream> struct S { // three-bit […]

C++_step_by_step之智能指针(三):shared_ptr

June 4, 2016 at 11:29 pm

本篇是C++_step_by_step系列智能指针专题的第三篇,在前两篇的基础上,介绍C++11标准库中的一个智能指针,shared_ptr。由于各种原因这一篇一直拖到现在,之前已经复习了哪些内容有些忘了,说不定会有些重复。 本文大致按顺序包含如下内容: 1. shared_ptr的概念和接口 2. 引用计数的简单实现 3. 在UniquePointer基础上实现SharedPointer 4. make_shared及实现 shared_pointer的概念和接口 scoped_ptr和unique_ptr都删除了拷贝构造函数和拷贝赋值函数,这意味着它们所拥有的对象是不能被共享的,这大大限制了智能指针的使用范围。shared_ptr就是为了解决这一问题而设计的,它允许多个指针共同享有一个对象,并在最后一个享有这个对象的指针析构时将对象的内存释放掉。shared_ptr采用引用计数的方式来管理这个对象被拥有的数量,每进行一次拷贝赋值或拷贝构造,这个计数都会增加1,而每当一个指针析构,这个计数减少1,当计数达到0时,释放所持有的对象。标准库的shared_ptr还考虑了多线程情况下的一些问题,本文只讨论shared_ptr设计的核心,所以略去有关这部分的逻辑,以后有机会再追加相关的内容吧。 下面列出了shared_ptr的主要接口,和unique_ptr的接口调成了一样的顺序,并做了一些简化。 template <typename T> class shared_ptr{ public: typedef […]

C/C++/gcc不常用语法和用法合集

May 14, 2016 at 11:10 am

C、C++的语法涵盖面很广,还有一些初看比较难懂的用法,包括宏的使用、大小为0的数组等,另外gcc编译器还支持一些编译器优化相关的特殊用法,这些语法在大多数情况下不被用到,但是偶尔看到时又容易令人感到困惑,所以本篇用来做一个索引页,来包含这方面相关的内容。对于简单描述就可以理解的部分,直接放在本篇中,而对于需要更长篇幅描述的内容,以链接的形式给出。 本文包含的内容网上其实都有了,这里一方面是做一个汇总,另一方面是网上对于某个特性描述过多、过全而难以记忆,这里仅给出自己碰到的,方便自己记忆;有些特性描述过少,这里再给出自己的一些使用示例,增强理解。 [gcc]长度为0的数组 一个比较常见的形式如下所示: struct A { int len; char data[0]; }; 这不是标准的C语法(ANSI C),但是gcc编译器支持。它通常被放置在一个结构体的最后,表示的结构体有一个定长的头部和一个变长的数据(比如TCP段就有这样的性质)。 和使用char *data不同的是,data数组所包含的内存和整个结构体的内存是连续的,可以使用malloc分配一块连续的内存: int main() { int […]

C++_step_by_step之智能指针(二):unique_ptr

April 30, 2016 at 11:16 pm

本篇是C++_step_by_step系列智能指针专题的第二篇,在上一篇scoped_ptr的基础上,介绍C++11标准库中的一个智能指针,unique_ptr。本文大致按顺序包含如下内容: 1. unique_ptr的概念和接口 2. 在ScopedPointer基础上实现UniquePointer 3. make_unique及实现 4. 实现unique_ptr对于数组的特化版本 5. 删除器的概念及实现 unique_ptr的概念和接口 unique_ptr如它的名字一样,只能自己一个人独占相应对象的管理,这点上和scoped_ptr是相同的;不同的一点是unique_ptr不再限定死对象,而提供了release()接口,它将对象指针返回,并将内部成员变量置空,从而交出这个对象的管理权;此外,unique_ptr同时支持单个对象和对象数组的管理,这是通过特化实现的,在第4部分我们再来讨论特化的版本,接下来讨论的都是单对象的版本。unique_ptr还提供了移动构造,以适用于STL容器,它还可以带有一个删除器参数,用于扩展它的使用范围,我们在最后一部分再来讨论删除器相关的内容。 下面给出了unique_ptr的大部分接口,均移除了删除器相关的内容: namespace std{ template <typename T, typename […]

C++_step_by_step之智能指针(一):scoped_ptr及其应用

April 30, 2016 at 5:24 pm

长达十多天的不可抗因素终于没了,希望能快速回到“图论算法漫谈”系列中去。今天先挖一个新的坑,"C++_step_by_step"系列,主要打算是复习和总结复习到、学习到的以C++语言为核心的知识点。 “智能指针”这个系列主要是对C++中智能指针相关内容进行的复习、总结,初步的规划是分成四个部分: 1. scoped_ptr 2. unique_ptr 3. shared_ptr 4. weak_ptr和intrusive_ptr 大体的内容包括这些智能指针的适用范围、提供的接口、实现以及应用的举例。 本文作为开篇,讨论最简单的智能指针scoped_ptr,涵盖的内容有: 1. scoped_ptr的概念、接口 2. 如何step by step实现一个scoped_ptr(使用C++11) 3. scoped_ptr用于bridge […]

QT的两个参数记录

April 4, 2015 at 11:12 am

QT工程配置文件中的两个参数每次都记不住,直接记在这里方便查把... QMAKE_CXXFLAGS:用于添加编译选项,比如 QMAKE_CXXFLAGS += --std=c++0x INCLUDEPATH:用于添加头文件查询目录,比如 INCLUDEPATH += /home/zyd/Downloads/boost_1_57_0

C++11 enum新特性

March 11, 2015 at 2:55 pm

在C++11以前的C++版本中,enum和C语言中是没有区别的。enum量是一个全局的整型量,比如像下面这样的代码是无法通过编译的。 // this code won't compile! enum Color {RED, GREEN, BLUE}; enum Feelings {EXCITED, MOODY, BLUE}; Color中的BLUE和Feelings中的BLUE会被当成同一个量。另外一方面,由于仅仅是整型的,所以Color中的GREEN可以和Feeling中的MOODY相比较。 C++11引入了一种强类型枚举,成为枚举类[enum class]。它的语法是在enum后面增加一个class关键字,如下所示。 // […]

C/C++ enum使用小tip

January 17, 2015 at 11:36 pm

最近打算把这些小tip也放到这里来,也算是填充一下什么都没有的blog。 对于不显式赋值的enum成员,可以在结尾加上一个MAXIMUM_BLABLA,这样以后如果有某种建立关于每一个enum成员的数组时,就可以使用MAXIMUM_BLABLA作为enum成员的成员数来使用,一旦需要改动enum的成员,只要使用这个值,其它地方的代码就都不需要改了。 希望以后有用到这个tip的时候。 enum WEEK{ MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY, MAXIMUM_DAYS }; TASK daily_task[MAXIMUM_DAYS];