C++
文章平均质量分 69
brahmsjiang
这个作者很懒,什么都没留下…
展开
-
分配自定义内存对齐的内存块的aligned_malloc实现分析
于是通过运算reinterpret_cast(reqBlockAddr + offset) & (~alignment),注意这里的alignment已经自减了(如31),结合刚刚所说31的意义,(reqBlockAddr + offset)即(reqBlockAddr + sizeof(void*) + (--alignment))这个地址不但剔除了个额外备用指针,还把31个byte的余量都剔除了,该地址到内存块末尾正好是我们申请的内存100byte。这样对常规的数据来说没有问题。原创 2024-06-24 11:54:17 · 272 阅读 · 0 评论 -
C++可变参数模板类通过递归和特化方式展开
可以看到普通版本压根没有起作用,原书中普通模板的写法其实误导了我,以为Contains匹配特化版而Contains匹配普通版,其实不是的。除了第一行的template外,只要类名后面还带有有尖括号的叫做模板特化,也就是说这段code第一个模板是Contains普通模板,后面两个是Contains特化模板。于是乎,当语句Contains::value想要实例化时尽量先找特化版本,无特化可选才匹配普通版本,下面是借助。原创 2024-05-09 17:22:39 · 321 阅读 · 0 评论 -
C++可变参数模板中的省略号
看可变参数模板代码时常会遇到省略号的使用,这类奇特的“...”出现位置还不固定,容易引起困惑。C++最近一直不用都快废了,在此想对省略号的使用做个简单归纳以提醒自己。可变参数模板以两种方式使用省略号。在参数名称的左侧,表示“参数包”,在参数名称的右侧,意为将参数包逐项展开。原创 2024-05-01 19:52:17 · 346 阅读 · 0 评论 -
《STL源码剖析》理解之将类成员函数和for_each等算法结合
既然抱怨的是“_Func这个函数不能转为接受一个参数的函数”,但以上代码使用的函数“print2”明明是只接受一个参数的函数,那为什么编译器还会报这个错呢?显然print2的参数是int而不是Int。mem_fun_ref返回一个仿函数,而这个仿函数接受两个参数,一个是T*指针(也就是方法所在类对象的指针,可理解为this),第二个才是我们需要的Int。类成员函数可以通过函数适配器(function adapters)包装成一个仿函数(重载了operator()的类),将其搭配于STL算法一起使用。原创 2023-02-24 23:48:34 · 429 阅读 · 0 评论 -
嵌入式Linux为Qt定制keymap
而嵌入式平台按键有限且要自行指定keycode,这时不再使用上述keymapDefault的缺省实现.比如将输入设备gpiokeys实现为驱动/dev/input/event1(假如他的F8keycode是82,非66),那么如何让Qt使用/dev/input/event1并使用新的keycode--Key_F8映射关系呢?...原创 2022-07-25 22:46:28 · 655 阅读 · 1 评论 -
More Effective C++ (3)笔记之不要期望以多态处理数组 & 重载<<操作符
多态指的是可以通过基类类型的指针或引用, 来操作派生类的对象. 然而通过基类类型的指针或引用,来操作派生类的对象数组, 则没有任何保证如预期般运作.有一个class BST以及继承自BST的class BalancedBST:class BST{public: BST():bst1(-1),bst2(-2){} virtual ~BST(){cout << "BST::~BST" << endl;} virtual ostream& op原创 2022-05-15 18:16:32 · 193 阅读 · 0 评论 -
对于何时调用构造函数、copy构造、赋值运算符的区分
有个Obj类:class Obj{public: Obj() : mem(0) { cout << "Obj()" << endl; } Obj(int n) : mem(n) { cout << "Obj(int n)" << endl; } Obj(const Obj& obj) { mem = obj.mem; cout << "Obj(const Obj& obj)" <<原创 2021-03-07 10:02:54 · 123 阅读 · 0 评论 -
C++引用拾遗
引用是变量的别名;在某种场合以引用替代指针是C++区别于C的一个显著特征;引用内部是用指针实现的。1. 如果将引用赋值给一个普通(非引用)变量会发生什么:int glbVar = 10;int& retRef(){ return glbVar;}int main(int argc, char* argv[]){ int tmp = 0; int* ptr_tmp = &tmp; tmp = retRef(); int&原创 2021-02-04 00:29:32 · 182 阅读 · 0 评论 -
代理、适配器和外观模式
重写基于另一组类的包装器接口是常有的事儿。创建包装器API的副作用是影响性能,函数调用开销+额外代码量,但为了创建更有针对性、质量更高的API是值得的。原创 2020-12-18 16:11:18 · 144 阅读 · 1 评论 -
简单工厂和扩展工厂模式
工厂模式一个创建型的设计模式。它允许创造对象时不用知晓所创建对象的具体类型。一般C++的构造函数有以下限制:1. 没有返回值2. 命名限制(构造函数名字必须和类名字相同)3. 不能声明虚构造函数4. 静态绑定创建(构造函数没有运行时动态绑定的概念,编译时须能够确定具体类型名)而工厂模式绕开了以上限制。它们经常和继承一起使用,即派生类能够重写方法并返回派生类的实例。常见做法是使用抽象基类。简单工厂抽象基类是包含纯虚函数的类,不能使用new实例化。其用于描述各个类共享的行为,指定了派生类必原创 2020-12-16 17:35:35 · 215 阅读 · 0 评论 -
单例线程安全实现、DCLP及其注意事项、饿汉懒汉实现方式
单例设计模式确保一个类仅存在一个实例,并提供了对此唯一实例的全局访问点。可以认为单例是一种更加优雅的全局变量。相对于全局变量,它还有其他优点:1. 确保一个类只创建一个实例2. 为对象分配和销毁提供控制3. 支持线程安全地访问对象的全局状态4. 避免污染全局名字空间用C++实现单例为了阻止客户自行分配、销毁、复制该类对象,将默认构造、析构、复制构造和赋值操作符都声明为私有并且不实现。class Singleton{public: static Singleton&原创 2020-12-14 22:58:28 · 237 阅读 · 0 评论 -
JNI应用笔记(陆续更新)
实例引用,与一个数组和java.lang.Object类或它的子类的实例对应:jobject类引用,与java.lang.Class实例对应,它代表着类的类型:jclass通过对象实例获取类(以实例引用获得类引用):jobject callbackListenerjclass clazz = env->GetObjectClass(callbackListene...原创 2020-03-19 16:11:00 · 142 阅读 · 0 评论 -
将XML node转为字符串(C++)
想得到这么一个字符串:<vtml_phoneme alphabet="x-ntsampa" lang="GER" ph="'?al|t@ 'pOst|Stra:|s@">Alte PoststraÃe</vtml_phoneme>看到项目用的XML库是TinyXML,我想先生成Node再转为字符串这个方法来的比较直接,于是翻阅网络发现是可以办到的:TiXml...原创 2020-02-29 22:51:42 · 1000 阅读 · 0 评论 -
UNICODE和UTF-8的相互转换(C++)
最近工作需要在xml node的节点中加入一些Unicode编码的某些国家的字符,比如“Alte Poststraße”,最后把xml node变成字符串传送给HMI,想要的效果是:<vtml_phoneme alphabet="x-ntsampa" lang="GER" ph="'has|%lO|x6 'Stra:|s@">Alte Poststraße</vtml_ph...原创 2020-02-29 22:15:32 · 1668 阅读 · 0 评论 -
使用vector存放pair对象
阅读陈硕的《Linux多线程服务端编程》中以shared_ptr实现读写锁一节中,使用了map<string, vector<pair<string, int>>>。一般关联对象都会放在map或者hash_map中,这样做是为了查询速度快,SGISTL中map是红黑树结构,即每个节点要存放3个指针,分别是父节点,左子节点,右子节点,如果存入map的对象比较小且数...原创 2019-10-31 17:52:31 · 2601 阅读 · 0 评论 -
notify_one与notify_all的区别以及虚假唤醒(spurious wakeup)
notify_all对应linux下的pthread_cond_broadcast:通常表明状态变化,比如某一主线程的任务完成,通知其余子线程开始执行。会使得所有wait在条件变量上的子线程去竞争锁。因为wait()会原子地unlockmutex并进入等待,而被唤醒的线程会在wait()退出时自动重新加锁。notify_one对应linux下的pthread_cond_signal:通常用于资...原创 2019-10-29 17:52:56 · 5716 阅读 · 0 评论 -
C++map key不存在
C++ map注意事项1、在map中,由key查找value时,首先要判断map中是否包含key。2、如果不检查,直接返回map[key],可能会出现意想不到的行为。如果map包含key,没有问题,如果map不包含key,使用下标有一个危险的副作用,会在map中插入一个key的元素,value取默认值,返回value。也就是说,map[key]不可能返回null。3、map提供了两种方式...转载 2019-10-23 21:29:42 · 6121 阅读 · 0 评论 -
Effective C++ (E3 26)笔记之延后变量定义的时间
如果定义一个变量并且需要承受其构造和析构成本,那么应尽量直到使用该变量的前一个时刻才将其定义。若是提前定义而最终未使用该变量,则耗费构造、析构成本不可避免。有个加密password的函数,返回加密后password的字符串,见示例:std::string encryptPswd(const std::string& pswd){ if(pswd.length() < minpass原创 2018-01-20 18:49:29 · 171 阅读 · 0 评论 -
Effective C++ (E3 10、11)笔记之在operator=中返回*this、处理自我赋值
为了实现“连锁赋值”,即 Widget wig4,wig3; wig3.printname(); wig4.printname(); //continous assigiment wig4=wig3=wig1; wig3.printname(); wig4.printname();operator=必须返回一个reference指向操作符的左侧实参。这项不成文的规定同样适用于其他赋值...原创 2018-03-10 00:33:59 · 287 阅读 · 0 评论 -
用std::map、std::sort、冒泡对deque进行排序(C/C++)
同样是一道面试题,函数参数类型是deque。deque是双端队列属于动态数组类型,没有sort成员函数,只有借助其他算法或者支持排序的容器,拷贝回deque。(练习而已,时间空间复杂度不考虑了)一、直接调std::sort,参数分别为起始迭代器,结尾迭代器(指向末元素的后面一个):#include <iostream>#include <deque>#incl...原创 2018-03-10 01:36:26 · 5607 阅读 · 3 评论 -
C++对象数组的初始化
如果一个类有默认的构造函数,使用new动态实例化一个对象数组不是件难事,如下代码:class animal{public: animal():num(0) {} ~animal() {}private: int num;};Animal *ani = new Animal[5];delete[]ani;然而 new Obj[n]的形式...原创 2019-03-08 14:50:33 · 16098 阅读 · 0 评论 -
C++虚函数表的理解、通过虚函数表访问非public成员函数
阅读了陈皓老师的虚函数表解析: 点击打开链接 ,以及虚函数表存放位置一文:点击打开链接对C++如何实现多态应该有了个粗浅认识.1)虚函数表是一个数组,每个元素存储virtual函数的指针2)如果一个类存在虚函数,编译器一般会将该类实例的前4/8个字节(取决于系统位数以及编译器)初始化为虚函数表的地址.3)虚函数表是针对类而言的,类似于static成员变量,存放在全原创 2018-01-16 23:20:12 · 1412 阅读 · 2 评论 -
Effective C++ (E3 43)笔记之学会处理模板化基类内的名称
有个程序要传送信息到不同公司,信息可能是密码也可以能使未经处理的。传送的不同公司的代码不同,在编译期间我们有足够信息决定传送到哪一个公司,于是采用基于template的解法:class CompanyA{public: void sendClrText(const std::string& str) { cout"<<str.data()<<endl; } void send原创 2018-02-04 17:20:34 · 219 阅读 · 0 评论 -
《Linux0.11源码解读》理解(五) head之开启分页
一个页表的最后一项在页表中的偏移地址是1023*4 = 4092(表项从0到1023,偏移地址=序号*4)。在保护模式下,ds段选择子,如0x10指向的是全局描述符表中的第二个段描述符(数据段描述符),里面内容中的段基址是 0。然后开启分页(cr0 的PG 标志,位31)。,共有4个页表只需设置4项(页目录和每个页表项本身也占据4K,每项4byte,一共可以设置1k个项/条目)。,共有:4(页表)*1024(项/页表)=4096 项(0 - 0xfff),也即能映射物理内存4096*4K = 16M。原创 2023-07-18 22:45:49 · 479 阅读 · 0 评论 -
Effective C++ (E3 31)笔记之降低文件间编译依赖 & 前向声明
有个Preson类,h文件中声明、cpp文件中定义(实现):#include <string>#include <memory>#include <iostream>class Person{public: Person(const std::string& name); std::string name() const;pr...原创 2018-01-06 23:59:47 · 297 阅读 · 0 评论 -
Effective C++ (E3 13)笔记之以对象管理资源
在Effective C++的“资源管理”一章中,讨论了如何以对象管理资源的方法。以我现在理解来看,是为了方便用户通过API管理资源,尤其是引导其正确地使用资源。当用户取得一个指向某对象/资源的指针时(一般在堆中构建),何时delete该对象取决于用户,甚至无法预测(如在析构前抛出异常)。从而造成内存泄漏等问题。解决上述问题的机制便是RAII,实现要点有:1.把指向资源的指针保原创 2017-12-29 12:27:10 · 158 阅读 · 0 评论 -
C/C++ static 关键字
C:局部静态变量:在声明时即被首次初始化(默认为0),以后调用不再初始化。生命周期从初始化直到程序结束,保存在数据段。只对局部作用域可见。全局静态变量:在声明时即被初始化(默认为0),生命周期从初始化直到程序结束,保存在数据段。只对本文件可见。全局静态函数:只对本文件可见。C++:静态数据成员:不隶属于任何一个对象实例,可理解为类的一个属性。生命周期从初原创 2018-01-03 22:54:45 · 197 阅读 · 0 评论 -
Effective C++ (E3 35)笔记之替代virtual函数的若干方案
假设要设计个游戏,里面不同类人物有不同生命值的计算方法:那么基类定义一个impure virtual health函数,让派生类去同时继承它的接口和一份缺省实现,当然也可以重新定义。这是一个最常见而无甚新意的设计。现有几种替代设计方案。一、用NVI(non-virtual interface)手法实现template methodclass chara{public: vi原创 2018-01-13 23:38:19 · 206 阅读 · 0 评论 -
Effective C++ (E3 20、21)笔记之以传const引用代替传值、谨慎指定返回类型
传递函数参数时,使用传值方式会对传入对象进行复制。如以下代码:#include using namespace std;class A{public: A(){ cout<<"A::A()"<<endl; } virtual ~A(){ cout<<"A::~A()"<<endl; } A(const A&){ cout<<"A::A(const A&)"<原创 2018-01-13 21:22:57 · 194 阅读 · 0 评论 -
Effective C++ (E3 33)笔记之名称遮掩规则及其应对手法
C++中名称遮掩规则即为:遮掩名称。这个遮掩的名称和类型无关。编译器按照从最内部作用域向外逐个查找,直到找到匹配的名称为止。Base类:#includeusing namespace std;class Base{private: int x;public: virtual void mf1()=0; virtual void mf1(int){ cout<<"原创 2018-01-13 00:47:22 · 251 阅读 · 0 评论 -
Effective C++ (E3 34、36)笔记之接口继承和实现继承
当类的成员函数为pure virtual、impure virtual、non-virtual时,派生类对这些函数进行继承其意义是不同的:pure virtual:只继承接口impure virtual:继承接口和一份缺省实现non-virtual:继承类继承其接口以及一份强制性实现,继承类绝不应该重新定义现在先从impure virtual讨论。有一个类描述飞原创 2018-01-13 01:56:27 · 243 阅读 · 0 评论 -
Effective C++ (E3 7)笔记之为多态基类声明virtual析构函数
#include#includeusing namespace std;class A{public: A(){ cout<<"A: cons"<<endl; } virtual ~A(){ cout<<"A: des"<<endl; } virtual void print(){ cout<<"A原创 2017-12-29 15:13:41 · 265 阅读 · 0 评论 -
友元类,友元函数
可以将一个类(B)声明为当前类(A)的友元。此时,当前类(A)的友元类(B)中的所有成员函数都是当前类的友元函数,可以访问当前类的private成员。友元函数可以同时访问多个类的private成员。class B; //对B类的提前引用声明class A{public:。。。friend class B;//将B类声明为当前类的友元类friend void call(Ti转载 2017-12-15 11:55:11 · 125 阅读 · 0 评论 -
Effective C++ (E3 22、23)笔记之成员变量声明为private、以非成员非友元函数替代成员函数
成员变量就应该是private。理由一:语法一致性。对客户而言每样东西都是函数。理由二:可通过成员函数严格控制其读写权限、添加约束条件。根本理由:封装性。声明为private则客户只能通过函数接口访问,客户不用关心实现方法,这为“所有可能实现”提供了弹性。并且以接口替代直接对变量的访问,从代码破坏量来说,前者将远远小于后者。客户很可能只需重新编译,甚至可以消除重新编译(条款31)。原创 2018-01-24 22:03:10 · 273 阅读 · 0 评论 -
Effective C++ (E3 5、6)笔记之禁止默认拷贝构造和赋值重载操作符
即使声明一个空类class A{}编译器会默认指定四个函数:default构造函数、析构函数、拷贝构造函数、赋值重载操作符class A{ A(){} ~A(){} A(const A&){...} //源对象的每一个non-static成员变量拷贝到目标对象 const A& operator=(const A& rhs){...}原创 2017-12-29 14:41:29 · 250 阅读 · 0 评论 -
C++的内部链接、外部链接及inline函数的探讨
先是几个概念:编译单元:首先明确,只有源文件(.cpp/.c)才能被编译器编译。预处理器首先递归包含头文件,形成一个含所有必要信息的单个源文件,此源文件就是一个编译单元。我可将其理解为被预处理后,包含头文件的.cpp文件。内部连接:如果一个编译单元(.cpp)内的名称对编译单元(.cpp)来说是局部的,在链接的时候其他的编译单元无法链接到它且不会与其它编译单元(.cpp)中...原创 2018-01-05 21:11:32 · 1525 阅读 · 0 评论 -
Effective C++ (E3 1)笔记之视C++为一个语言联邦
应该将C++视为一个由相关语言组成的语言联邦而非单一语言。其主要的次语言一共有四个:C面向过程部分,包括区块、语句、预处理器、内置数据类型、数组、指针等。面对一些问题时,C++只不过是高级的C解法。但是注意,C没有C++的模板、异常、重载。。。面向对象C++面向对象部分,包括类(构造析构)、封装、继承、多态等。是面向对象设计之古典守则在C++上最直接的实施。Template C原创 2018-02-04 15:49:33 · 157 阅读 · 0 评论 -
Effective C++ (E3 42)笔记之了解typename的双重意义、嵌套类型的使用
template class Widget;templateclass Widget;对于这两个声明式,在声明模板参数时,关键字class和typename意义完全相同。然后有时,却只能使用typename。如有以下模板:templatevoid print2nd(const C& container){ if(container.size() >= 2) { typena原创 2018-02-04 15:08:57 · 243 阅读 · 0 评论 -
Effective C++ (E3 41)笔记之了解隐式接口和编译器多态
对于class而言,接口是显式的,以函数签名式(函数名、参数类型、返回类型)为根基。多态则是通过virtual函数发生在运行期。如有个类widget:class Widget{public: Widget(std::string name="default", std::size_t size=0) :sname(name), ssize(size) { } Widget原创 2018-02-04 14:02:06 · 328 阅读 · 0 评论 -
Effective C++ (E3 25)笔记之写一个不抛异常的swap函数
STL的swap可以说是异常安全编程的脊柱,以及是用来处理自我复制可能性的一个常见机制。典型实现如下:namespace std{ template void swap(T& a, T& b) { T temp(a); a = b; b = temp; }}但其用到三个对象的复制,即a复制到temp,b赋值到a,temp赋值到b。对于某些handle类(使用pim原创 2018-02-03 12:38:03 · 177 阅读 · 0 评论