
c/c++
文章平均质量分 86
c 和 c++ 总结
王YANLONG
技术总结,自我沉淀
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
uml类关系(实现、继承,聚合、组合,依赖、关联)
drawio和EA是架构设计时经常使用的画图工具。drawio学习门槛低,使用灵活,但是功能仅仅限于画图。EA学习门槛高,但是功能更加的丰富:①在画图方面,EA严格满足UML标准,EA中的图和类是关联的,如果修改了一个类的名字或者函数等,在引用这个类的图中也会自动修改②EA还可以将架构设计时定义的类、接口等导出为代码③EA可以导入已有的代码,生成类图。原创 2025-04-26 17:40:21 · 1136 阅读 · 0 评论 -
std::thread:join/detach
用于线程间同步,特别是在主线程退出的时候,等待进程中的所有其它线程都退出之后,主线程再退出,这样能保证进程安全的退出。试想,如果主线程退出的时候,有其它线程还在运行,很容易导致进程的退出码不是0,或者被信号杀死。因为进程退出的时候就要释放所有的资源,而此时还在运行的线程可能会使用已经释放的资源,这样就会导致段错误。调用join之前,需要使用joinable进行判断现成是不是可join,如果线程不可join,那么调用join会抛异常。原创 2025-03-02 15:18:05 · 520 阅读 · 0 评论 -
std::cout两个坑
使用std::cout打印char类型的指针,如果这个指针为空的话,那么会导致后边使用std::cout进行的打印都不显示。(2)打印空的char指针,会导致后边的std::cout打印都打印不出来。(3)打印空的int指针,没有影响,将空指针当成0打印了出来。(1)打印非空的char指针,执行正常。原创 2024-11-16 19:59:37 · 199 阅读 · 0 评论 -
c++类模板为什么不能编译到动态库中来使用
在使用c++的时候,我们习惯于将类的定义声明在头文件中,即.h文件中,将类函数的实现定义在源文件中,即.cpp文件。如果我们要提供的是一个动态库,那么这种方式更常用,使用动态库的时候,包含头文件,编译的时候链接动态库就可以了。原创 2024-09-15 12:02:51 · 605 阅读 · 0 评论 -
cyberrt:TimingWheel单例分析
单例模式要求一个类在一个进程中只能创建一个对象。比如 cyberrt 中的 TimingWheel 类就是单例模式,这个类管理着一个进程内的所有定时器,只需要一个对象就可以。单例模式的实现有两种方式,懒汉式和饿汉式。懒汉式,当第一次使用的时候才会真正创建这个对象;饿汉式,不管会不会用到这个对象,在进程启动的时候都会创建这个对象,如果一直不使用,那么就会造成资源浪费。饿汉式的缺点是可能造成资源浪费,但是对性能友好,因为在进程启动的时候就直接创建了,需要使用的时候可以直接拿来使用;懒汉式反之。原创 2024-02-24 15:46:57 · 867 阅读 · 0 评论 -
c语言中的常量(const变量),在任何情况下都不能修改吗?
从如下截图中可以看出,目标文件主要包括代码段 .text,数据段 .data, .bss 段,只读数据段 .rodata。其中只读数据段的长度是 8,正好和上边的代码相匹配,两个 int 类型,长度是 8。但是如果把变量的地址取出来,然后通过地址操作来间接修改 const 变量,这个时候可以编译通过。“c 语言中 const 修饰的变量是一个常量,常量在程序运行时不能修改,只能在变量声明的时候初始化。const 变量直接赋值,不管是全局变量还是局部变量,编译的时候会报错,编译不通过。用下边的代码来做实验。原创 2024-01-13 14:01:26 · 859 阅读 · 0 评论 -
实例观察c语言中volatile的作用
volatile 意思是易变的。在 c 语言中,如果变量被 volatile 修饰,就是告诉编译器这个变量随时都可能发生变化,那么每次读取变量的时候都会到内存中读取。如果变量没有被 volatile 修饰,并且编译器发现在多次读取变量之间,变量没有被修改,那么编译器可能将变量的值保存到寄存器中,这样在后边访问变量的时候性能会得到提升。但是如果变量以编译器无法识别的方式被修改,那么这个时候将变量的值保存在寄存器中就可能引入问题。原创 2024-02-17 16:47:39 · 1311 阅读 · 1 评论 -
c 语言中的指针和数组
声明的局部变量数组,如果没有初始化,那么数组保存在栈上,数组的内容是不确定的。局部变量不像全局变量,全局变量如果没初始化,那么默认是全 0。将数组初始化为 0 的方式主要有以下 3 种,本人在开发过程中习惯于使用第一种,即使用 {0} 将数组初始化为全 0。(1)数组声明的时候使用 {0} 初始化使用 memset() 将数组设置成 0。(3)使用 for 循环将数组元组逐个设置为 0。原创 2024-02-18 12:11:38 · 2884 阅读 · 0 评论 -
实例观察c++返回值优化
如下代码,在 MakeObj() 中创建了一个局部对象 obj,并将 obj 返回。Test() 函数调用了 MakeObj(),并将 MakeObj() 的返回值赋值给了 obj。按我们的预期,MakeObj() 是值返回,在 main() 调用 Test() 的过程中,应该发生了两次构造和两次析构。:默认构造,在 MakeObj() 声明局部变量的时候。拷贝构造,在 MakeObj() 返回的时候,将返回值赋值给 Test() 中的局部变量 obj 时。原创 2024-02-24 12:20:00 · 480 阅读 · 0 评论 -
cyberrt:组件加载器
cyberrt 加载运行组件的时候,首先要加载用户的动态库。动态库的加载通过类 ClassLoader 来完成。(1)动态库加载函数 dlopen()底层动态库的加载是通过函数 dlopen() 完成。dlopen() 可以直接传动态库的名字,比如 libcamera.so,也可以传动态库的路径,比如 /ads/lib/libcamera.so。原创 2024-02-24 21:16:03 · 1379 阅读 · 0 评论 -
public, private, protected, friend
权限管理是 c++ 的一大特点,面向对象语言封装的特性也给权限管理带了了方便。c++ 中的权限主要有 3 种:public,private,protected。类中的函数和属性默认是 private 的,类的继承关系默认也是 private 的。public,private,protected 的使用场景有两个:修饰类成员以及修饰类的继承关系。本文先记录这 3 个权限修饰符修饰类成员以及继承关系,最后再记录 friend 的使用。原创 2024-02-25 10:46:16 · 1202 阅读 · 0 评论 -
深拷贝和浅拷贝,拷贝构造、赋值运算符
拷贝构造在如下场景会被调用:(1)函数调用时,函数参数是对象的值传递(2)声明对象同时初始化的时候(而不是声明和初始化分开,因为声明的时候就创建了对象)(3)函数返回的时候,返回对象的值。第 3 种情况,默认情况下有返回值优化,不会调用拷贝构造函数。通过编译参数 -fno-elide-constructors 可以禁用返回值优化。拷贝构造函数的形参必须是引用传递,如果是值传递的话,那么在传递过程中也会调用拷贝构造函数,这样就造成递归调用。如果是值传递,会有编译错误。原创 2024-02-25 17:10:38 · 1381 阅读 · 0 评论 -
char * 和 std::string
实例代码如下图所示,s1 和 s2 均是常量字符串,字符串常量保存在只读数据区,是只读的,不能写,代码中注释的那两行代码会导致段错误。s3 是字符数组,字符数组是可以修改的,std::string 类型的字符串也是可以修改的。代码运行之后,可以看到 s1 和 s2 是常量字符串,这两个指针指向的地址也是相同的。从 s1,s2 的地址和 s3,s4 的地址对比可以看出,s3 和 s4 的地址相距比较近,和 s1、s2 的地址相距比较远。原创 2024-02-25 20:55:59 · 1449 阅读 · 0 评论 -
智能指针(shared_ptr, weak_ptr, unique_ptr)
c++ 中的智能指针让 c++ 看起来像 java,go 这种带 GC 的语言,但和 GC 又不完全相同。c++ 中的智能指针使用引用计数,当引用计数减为 0 的时候就会立即释放资源,释放资源具有实时性;而像 java,go 这样的 GC 语言,当对象不被引用时,可能不会立即释放资源,资源的释放有滞后性。如果不使用智能指针,需要开发者使用 new 和 delete 创建和销毁对象。使用智能指针,开发者不需要手动来释放资源,当引用计数变为 0 时自动释放。就这一个好处。原创 2024-02-26 09:55:59 · 968 阅读 · 0 评论 -
大端,小端;网络序,主机序
在网络编程中,特别是底层网卡驱动开发时,常常遇到字节序问题。字节序指的是多字节数据类型在内存中存放的顺序,高位保存在低地址还是高地址,以此来划分大端还是小端。原创 2024-02-26 20:31:37 · 2160 阅读 · 0 评论 -
c/c++ static 关键字
1 static 修饰变量从修饰的对象来看,static 可以修饰局部变量,也可以修饰全局变量,可以修饰函数;可以修饰类中的成员变量以及成员函数。从生命周期的角度来看,static 修饰的对象的生命周期,与进程的生命周期是一致的。从作用域的角度来看,局部静态变量的作用域是函数内,全局静态变量的作用域是模块内;类中的静态成员变量和成员函数的作用域,能访问到类的地方都可以访问到静态成员,类中的静态成员同时也受 public,private,protected 权限修饰符的影响。原创 2024-02-27 10:47:59 · 1173 阅读 · 0 评论 -
[c++] c++ 中的顺序(构造,析构,初始化列表,继承)
对象构造的时候,对象成员变量的初始化顺序是什么样的?派生类构造的时候,先构造基类还是先构造派生类?构造函数中的初始化列表,初始化的顺序是列表的顺序吗?析构的时候,析构的顺序是什么样的?本文通过实例代码记录上述场景下的顺序。先说结论:(1)全局对象以及静态全局对象,在 main 函数调用之前创建(2)构造时,先构造类中的成员变量,再调用构造函数(3)类中成员变量的构造顺序是变量在类中声明的顺序(4)初始化列表中,成员变量的初始化顺序也是变量在类中声明的顺序。原创 2024-03-03 13:25:00 · 2212 阅读 · 0 评论 -
[c/c++] 结构体对齐
在 c 语言中,结构体的大小并不是结构体每个成员的大小之和,结构体的大小往往比结构体的成员大小之和要大。如下结构体,每个成员的大小分别是 1、4、1,但是结构体的大小却不是 6,而是 8。char a;int b;char c;自然对齐:如果一个数据的内存地址正好是这个数据大小的整数倍,那么说这个数据是自然对齐的。比在 64 位机器上,一个 int 类型的数据地址是 4 的整数倍,一个 long 类型的数据地址是 8 的整数倍,那么说这两个数据是自然对齐的。原创 2024-03-04 12:06:13 · 726 阅读 · 0 评论 -
c和c++中const常见问题
const 和 #define 的区别?const 和指针一块出现的时候,到底谁不能修改?const 和 volatile 能同时修饰一个变量吗?const 在 c++ 中的作用?原创 2024-03-06 10:53:56 · 1078 阅读 · 0 评论 -
c++模板
c++ 中的模板通过将类型参数化,可以提高代码的复用性。模板并不能减少代码量,只是从开发者的角度来看,代码量减少了,复用性提高了;从二进制文件的角度看,代码量没有减小。原创 2024-03-07 17:37:59 · 616 阅读 · 0 评论 -
设计模式:模板模式
在上边的例子中,thread_entry() 就是一个模板方法,其中对 init(),should_stop(),do(),prepare_stop() 进行了调用。thread_entry() 的实现是不变的,是一个模板。init(),should_stop(),do(),prepare_stop() 需要派生类来实现,用户不需要关心这几个函数是怎么调用的。其中 init(),should_stop(),do(),prepare_stop() 均声明为纯虚函数,也就是需要子类来实现的函数。原创 2024-03-10 18:36:21 · 470 阅读 · 0 评论 -
查表 —— 策略模式和职责链模式的核心
查表法在工厂模式、策略模式以及职责链模式中都有使用。以工厂模式为例,表中存储的数据,key 是商品的类型,value 是生产这个商品的工厂。在生产商品的时候,直接根据商品类型从表中获得商品对应的工厂,然后通过工厂生产商品。如果没有表的话,那么类型判断和工厂实现都在一块,代码耦合度高,通过查表法可以对代码进行解耦。原创 2024-03-10 22:57:04 · 974 阅读 · 0 评论 -
c++右值引用
在说右值引用之前,需要先说一下左值引用。左值引用类似于c语言中经常使用的指针,c++引入左值引用,在一定程度上可以代替指针。什么是左值,简单来说,左值是等号左边的值,是可以取地址的。左值引用就是左值的别名,左值引用和左值指向同一块内存;左值引用就像人的小名,指的是同一个人,这个人长高了5cm,那么说这个人的大名和小名的时候,都长高了5cm。如下代码,是左值引用的例子:(1)左值引用需要在声明的时候初始化(2)左值引用不能指向一个右值,但是const左值引用可以用一个右值进行初始化。原创 2024-03-13 11:20:31 · 1191 阅读 · 0 评论 -
std::future, std::promise, std::packaged_task, std::async
std::promise 进程间通信,std::packaged_task 任务封装,std::async 任务异步执行;std::future 获取结果。原创 2024-03-16 20:29:32 · 2097 阅读 · 0 评论 -
lambda 表达式
在 c++ 中,一个可以执行的任务有多种形式:函数,lambda 表达式,std::function 对象,std::bind 绑定的任务,std::packaged_task 封装的任务。原创 2024-03-17 13:51:27 · 1236 阅读 · 0 评论 -
基类构造函数和析构函数中调用的虚函数是基类的还是派生类的 ?
如下代码,Base 是基类,其中有 3 个虚函数 Do1(),Do2() 和 Do3(),另外还有一个非虚函数 Do()。Derived 是继承 Base 的派生类,在 Derived 中覆写了 Do1(),Do2() 和 Do3()。在 main() 函数中创建了一个 Derived 对象,并把指针赋值给 Base 类型的指针 b。使用 b 调用 Do1(),Do2() 和 Do3() 的时候,我们都知道调用的是 Derived 中的函数。原创 2024-03-23 16:25:20 · 1169 阅读 · 0 评论 -
c++ 中的一些关键字:explicit, delete, default, override, final, noexcept
explicit 的意思是清楚的,明显的。一般用在类的构造函数中,防止隐式转换。如下代码,(1) 类 A 的两个构造函数都没有使用 explicit 修饰,所以如下两行代码,隐式转换,是允许的A a1 = 1;(2) 类 B 的两个构造函数都使用 explicit 修饰了,不允许隐式构造,所以下边两行代码编译不通过B b1 = 1;(3) 类 B,如下代码,使用强制类型转换,是可以的。原创 2024-03-23 21:01:48 · 957 阅读 · 0 评论