C++中的问题
文章平均质量分 58
杀别人能摸牌
互相交流学习
展开
-
用基于范围的for循环遍历bitset的所有有效位置
标准库中的std::bitset,利用若干个uint32_t或者uint64_t作为存储单元,来表示多个位置的0-1状态,可以节约很多的空间。例如,有31组开关,最少可以只用一个uint32_t来存储这31组开关的状态,只占用4个字节。现在的需求是,对于这31组开关,依次找到其中打开的,做一系列的处理。标准的std::bitset并没有提供遍历的接口。在SGI版本的实现中,std::bitset有_Find_First()和_Find_Next()的接口,可以通过如下代码遍历:std::bit原创 2021-05-05 23:45:30 · 2499 阅读 · 2 评论 -
用位域模拟非字节对齐的整型(uint4_t,int4_t等)
与硬件打交道的时候,会存在不是字节对齐的整型,比如4位无符号整型(uint4_t)、24位有符号整型(int24_t)这种,如果直接用usinguint4_t = uint8_t; using int24_t = int32_t;这种别名的话,虽然也可以用用,但是当值溢出的时候,我们代码是没法发觉的,最终可能使用一个在表示范围外的值。此外当硬件传过来的数如果是一个负数,比如int4_t的-8(0x8),我们用int8_t变量接收的话,用int8_t的方法来解释,必然不是-8,而是8(0x08,符号位为0..原创 2021-03-21 20:59:11 · 1829 阅读 · 0 评论 -
判断tuple里面是否有某种类型的容器,然后将一个指针或者实体压入这个容器
工作中遇到一个需求,一个模块要处理很多种命令,这些命令定义成了不同的类,其中有些类是“收”命令,有些类是“发”命令。用户定义好命令对象会传给模块,如果是“收”命令,会在一定时间之后,检查传给模块的这个命令对象,看里面的值,收到的东西会写给这个命令对象。所以这些命令,一开始我都在模块内部存成指针,这样一个缺点就是需要保证模块在真正执行这个命令的时候,这个命令没有被析构,不然就成了野指针。这种粗暴情况下,我存命令的容器用一个std::tuple,里面存的是各种命令指针的std::deque,形如:te原创 2021-01-10 00:05:26 · 459 阅读 · 1 评论 -
利用SFINAE+模板函数偏特化,判断一系列类似的枚举是否有某种成员,并写针对这一系列的通用打印函数
SFINEA的概念就是在模板的实例化过程中,如果一种实例方法匹配失败了,不会报错,而是继续寻找其它实例方法。在最近的应用中,我碰到一个需要打印枚举的需求,打印枚举,一般的实现就是在打印枚举的函数里面写一个局部静态的哈希表(std::unordered_map),把枚举值和要输出的字符串一一对应。类似于这种: static const char* Enum2Str(Format content) { static auto && enum_map = []()原创 2020-12-13 01:35:42 · 444 阅读 · 0 评论 -
模板函数的偏特化探索
有一个生成坐标的函数,这个函数会受5个参数的影响,导致具体的实现有所不同,其中某些组合下的实现相同,为了让那个判断的函数简短一点,就想到用模板来做,并且会出现模板函数的全特化和偏特化的情况。但是C++目前的标准不允许模板函数存在偏特化,只允许模板类存在偏特化。我这五个变量都不是类型参数,而是值参数。由于不允许结构体作为模板的参数:我就想,能不能用常量表达式+联合体的方式,把一个结构体转换成整型?于是就动手写了一下。用联合体实现一个U16(unsigned short)和一个16原创 2020-12-09 20:48:49 · 390 阅读 · 0 评论 -
为什么modern C++中默认构造函数也最好加一对空的花括号?
C++11开始,变量的初始化除了=等号号还能用初始化列表{},其中在 Effective Modern C++ 中,作者还强调初始化列表可以解决以前的一个很恼火的问题,就是如果调用默认构造函数,不能在后面加空的括号,因为这会被解释成函数的声明:Widget w1; //默认构造函数Widget w2();//声明一个返回值为Widget类型、不接受参数的函数w2Widget w3{};//默认构造函数看到这里我就产生了疑惑:不加括号不就完了吗,同样也是调用默认构造函数呀?话是这么说,但我还是照着原创 2020-06-01 21:34:37 · 925 阅读 · 0 评论 -
含有虚函数的struct(class)内存对齐和空间大小的计算(win32)
考虑这样一个类b,依次包含一个虚指针、char、类a、int、double数组struct a { char c;//1+7 double d;//8};//16struct b { char c; a s; int i; double d[3]; virtual ~b() {}}; 按照道理来讲,虚指针vptr占用4字节,...原创 2018-09-10 18:27:32 · 1230 阅读 · 0 评论 -
华为笔试,语法树,用单行的类LISP语法字符串表示
有数字(0~9构成的正整数)、三种操作运算符(加法+、乘法*、自增^)、分隔符一个空格、左右括号表达式形式是“(运算符 参数)”形式比如(+ 3 4),求值结果7;(+ (* 2 3)(^4))求值结果11语法树结束后,后面加任何字符都是合法的,比如(+ (* 2 3)(^4)))))))#$是合法的匆匆忙忙地写了一个,感觉太长了。。。应该有很大的优化空间。主要思路:用一个va...原创 2018-08-15 22:18:06 · 974 阅读 · 0 评论 -
生产者消费者问题 C++解决方法
抄自维基百科 :生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了共享固定大小缓冲区的两个线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消...原创 2018-08-05 17:22:28 · 3095 阅读 · 0 评论 -
std::vector删除元素迭代器以及内存的变化
std::vector是顺序容器,当用erase成员函数删除一个迭代器指向的元素时,会自动移动(不是std::move)后面的元素到前面来,而迭代器的指向不变(如果是std::map、std::list这类关联型容器,迭代器会失效),并且不会回收内存(也就是capacity不会变)。当用swap成员函数跟自身的拷贝交换时,才能释放多余内存。代码如下,自定义一个foo类以监视构造、赋值、复制、...原创 2018-08-09 11:31:51 · 3546 阅读 · 0 评论 -
多线程问题,实现三个线程顺序循环输出123123123...
阿里中间件笔试题记录:有三个worker线程:worker1、worker2、worker3。三个线程分别只能输出1、2、3。请写出代码,实现三个线程顺序循环输出123123123...#include <iostream>#include <thread>//thread#include <condition_variable>//cond...原创 2018-07-10 20:31:17 · 2519 阅读 · 0 评论 -
因丑数问题联想到的STL迭代器失效问题·vector
今天写一个丑数的程序,一开始用的迭代器表示位置,写出了这个int GetUglyNumber_Solution(int index) { if (index <= 0) return 0;//返回错误信息 vector<int> uglyNums; uglyNums.push_back(1); //定义三个迭代器Tx,分别表示第一个乘以x后大于当前最大丑数的元素的...原创 2018-06-01 10:12:24 · 146 阅读 · 0 评论 -
char* x = new char[length]的问题
length 是字符长度,如"666"长度为3,但是直接new char[3],然后sprintf把666存进去,在delete[]的时候会卡住,new char[3+1]才行。char*类型经常容易忽略'\0'的存在 unsigned length = 0; int temp = i+1; while(temp != 0){ temp/=10; ++length; }...原创 2018-05-09 10:18:32 · 5423 阅读 · 0 评论 -
一个不容易混淆的方法区分诸如const int * 、int const *和int * const
参考这位的说法,具体代码 const int a = 1; int const b = 2;//&a 和 &b 是const int * 类型 a = 1;//错误 b = 1;//错误 const int * p1 = &a; int const * p2 = &a;//p1,p2不报错,说明两者等价 int * const p3 = &a;/...原创 2018-05-14 10:18:24 · 271 阅读 · 0 评论 -
关于C++内存泄漏的一些简单理解
关于类的自定义赋值运算符和复制构造函数的重要性。反面例子:class a{//没有自定义的复制构造函数和赋值运算符public: a(int num=0){ ptr = new int(num); } ~a(){ delete ptr; }private: int *ptr;};void doNothing(a dummy){}//值传递对象的危害int main(){ a x...原创 2018-05-15 09:51:20 · 186 阅读 · 0 评论 -
虚基类、虚拟继承、虚函数?
前几天师兄想考我什么是虚基类的时候,我说是因为多重继承中,如果出现菱形继承(multiple inheritance diamond),不想要末端派生类有两份最底层基类的数据的话,就得用虚拟继承。结果居然被怼了,说我说的啥玩意儿?我还以为我记错了,实际上是他把虚基类和含有虚拟函数的基类给混淆了。 今天读了Effective CPP,再总结一下虚基类把,就是被虚拟继承的基类。虚拟继承很少用到,...原创 2018-06-03 21:12:19 · 715 阅读 · 0 评论 -
无法用 "ATTRIB_GEN_STRING *" 类型的值初始化 "ATTRIB_GEN_NAME *&" 类型的引用(非常量限定)
在ACIS中,很多下行强制(downcast)转换是安全的,如对一个ENTITY*指针强制使用(BODY*)从来没有出现过问题。 今天碰到的是api_find_named_attribute这个函数,原型如下。 DECL_GA outcome api_find_named_attribute( ENTITY* ent, con...原创 2018-06-04 11:13:02 · 3517 阅读 · 1 评论 -
error LNK2019的一种原因
1>Link:1> 正在创建库 d:\documents\visual studio 2010\Projects\testDLL\Debug\testDLL.lib 和对象 d:\documents\visual studio 2010\Projects\testDLL\Debug\testDLL.exp1>cal.obj : error LNK2019: 无法解析的外部...原创 2018-05-23 22:10:38 · 2896 阅读 · 0 评论 -
两个单链表的第一个公共结点
方法1:由于是单链表,所以可以用一个set保存第一个的节点,然后遍历第二个链表,寻找相同的节点,时间复杂度O(MlogM),空间复杂度O(max(M,N)),代码 ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) { //最先想到的办法,空间复杂度O(M),时间复杂度O(max(M,N)) ...原创 2018-06-06 21:05:32 · 2408 阅读 · 0 评论 -
成员指针运算符 .* 和 ->*
指针是指向一些内存地址的变量,既可以是数据的地址也可以是函数的地址。C++的成员指针遵从同样的原则。困难的是所有的指针需要一个地址,但在类内部没有地址;选择一个类的成员意味着在类中偏移。只有把这个偏移和具体对象的开始地址结合,才能得到实际地址。成员指针的语法要求选择一个对象的同时逆向引用成员指针。struct simple { int a ; }simple so;simple*...转载 2018-06-14 17:24:56 · 3222 阅读 · 0 评论 -
C++用正则表达式,以及十六进制字符串转十进制数字的问题。
C++用正则表达式,以及十六进制字符串转十进制数字的问题。原创 2017-07-05 23:03:08 · 1724 阅读 · 0 评论