C++
文章平均质量分 61
xiaoju233
Talk is cheap, show me the code.
展开
-
C++STL中Allocator分析
C++STL中Allocator分析C++ SGI STL的allocator分为两级:第一级配置器:超过128bytes的内存分配通过第一级分配器进行分配。第二级配置器:不超过128bytes的内存分配通过第二级分配器进行分配。为了简单起见,文本在讨论的时候无考虑多线程的场景以及模板化。第一级配置器第一级配置器的实现比较简单,直接通过malloc请求内存,通过free释放内存。若通过malloc请求内存失败,则先尝试通过调用用户注册的处理函数尝试释放不再使用的内存,之后再次使用ma原创 2022-03-01 11:12:02 · 515 阅读 · 0 评论 -
简易协程库
协程本项目Github地址简介使用C++和x86汇编设计并实现了一个简易的有栈协程库。通过保存和恢复Callee Save寄存器的方式实现协程的切换。通过admin协程进行协程调度,每次协程调度都会先切换回admin,由admin选择下一个上台运行的协程。使用显示运行时打桩机制Hook常用的库函数例如read和accept函数等,改为使用非阻塞的方式调用,从而避免线程被挂起。从x86-64汇编开始Callee Save和Caller Save在x86-64体系结构中,寄存器可以分为两种:Call原创 2021-10-06 21:01:54 · 292 阅读 · 0 评论 -
C/C++内存对齐问题
为何需要内存对齐?尽管内存以字节为单位,但是大部分处理器并不是按照字节块来存取内存的。它一般会以双字节、四字节、8字节、16字节甚至32字节为单位来存取内存,这些存储单位被称为内存存取粒度。从Cache角度看从上图可以看出,一个cache line保存了2^b个字节。如果没有内存对齐规则,数据可以随意存放,那么可能导致一个变量被分隔在两个cache line中,这样处理器就需要读取两行cache line然后再将其合并成一个变量。从物理内存角度看从上图中可以看出内存模块由8个8Mx8的DRA原创 2021-07-12 17:05:09 · 312 阅读 · 1 评论 -
Make命令与Makefile文件
Make命令使用Make命令只会在必要时重新编译所有受改动影响的源文件。而不会因为只改动了一个文件而重新编译整个项目。Make命令不仅仅用于编译程序,无论何时,当需要通过多个输入文件来生成输出文件时,你都可以利用它来完成任务,它的其他用法还包括文档处理。make命令选项和参数:-k 让make命令在发现错误时仍然继续执行下去,而不是在检测到第一个错误时就停止。-n 让make命令输出将要执行的操作步骤,而不真正执行这些操作。-f 告诉make命令将哪一个文件作为makefile文件。若没有原创 2021-07-08 14:34:48 · 1318 阅读 · 0 评论 -
C++万能引用与完美转发
C++万能引用与完美转发什么是万能引用如果函数模板形参具备T&&型别,并且T的型别系推导而来,或如果对象使用auto&&声明其型别,则该形参或对象就是个万能引用。万能引用首先是一个引用,它既可以绑定到左值引用,也可以绑定到右值引用。先看个例子:extern "C"{ int printf(const char * format, ...);}template<typename T>void func(T& val){原创 2021-06-26 16:18:31 · 470 阅读 · 0 评论 -
C++ lambda表达式的使用
C++ lambda表达式的使用lambda语法如下:[函数对象参数](操作符重载函数参数) mutable 或 exception 声明 -> 返回值类型 {函数体}[函数对象参数]函数对象是传递给编译器自动生成的函数对象类的构造函数的。函数对象参数只能使用那些定义lambda表达式时,作用域内可见的局部变量。这部分不可省略。[] 没有任何函数对象参数。[=] 函数体可以使用可见的所有局部变量,按值传递。[&] 函数体可以使用可见的所有局部变量,按引用传递。[this] 函原创 2021-06-26 10:10:28 · 287 阅读 · 0 评论 -
c++中bind的参数传递方式
c++中bind的参数传递方式在bind函数中的参数传递方式看代码:extern "C"{ int printf(const char * format, ...);}#include<functional>void func(int val){ printf("Val = %d\n", val); return;}int main(){ int a = 520; auto callfunc = std::bind(func, a);原创 2021-06-25 19:16:49 · 1689 阅读 · 0 评论 -
vector容器初始化{}和()的区别
vector容器初始化{}和()的区别看代码:extern "C"{ int printf(const char * format, ...);}#include<vector>int main(){ std::vector<int> vec1{10, 20}; for(int i=0;i<vec1.size();i++){ printf("%d ", vec1[i]); } printf("\n");原创 2021-06-25 18:37:38 · 405 阅读 · 0 评论 -
C++在priority_queue中自定义比较函数
C++在priority_queue中自定义比较函数方法一可调用函数操作符的对象struct Node{ int val;};struct cmp{ bool operator()(const Node &a, const Node &b){ return a.val > b.val; }}priority_queue<Node, vector<Node>, cmp> q;方法二重载比较运算符s原创 2021-06-25 16:09:07 · 1350 阅读 · 0 评论 -
C++类内存布局(虚函数与虚继承)
C++类内存布局单继承class Base{ int x, y;};class Derive: public Base{ int z;};可以看到,在Derive类中,Base类的成员被放在了前面。多继承class Base1{ int x, y;};class Base2{ int a, b;};class Derive: public Base1, public Base2{ int z;};对于多继承而言,一般是按照原创 2021-06-01 10:34:08 · 605 阅读 · 3 评论 -
C++符号修饰Name-mangling
C++符号修饰C语言符号修饰在上古时期,编译器编译源代码产生目标文件时,符号名与相应的变量和函数的名字是一样的。比如一个汇编源代码里面包含一个函数foo,那么汇编器将其编译成目标文件后,foo在目标文件中的相应符号名也是foo。当后来UNIX平台和C语言发明是,已经存在了相当多的使用汇编编写的库和目标文件。这样就产生了一个问题,那就是如果一个C程序要使用这些库的话,C语言中不可以使用这些库中定义的函数和变量的名字作为符号名,否则会与现有的目标文件冲突。为了防止类似的符号名冲突,UNIX下的C语言就规定原创 2021-05-29 16:54:27 · 1051 阅读 · 1 评论 -
C++程序动态链接
C++程序动态链接关于动态链接的原理,可以先看下这篇先看代码://simpleApp.cppint foo(int a, int b);int main(){ int a = 0; int b = 1; int c; c = foo(a, b); return c;}[root@xxxx] g++ -c simpleApp.cpp #生成.o文件[root@xxxx] g++ -o simpleApp simpleAp原创 2021-05-29 16:27:22 · 1181 阅读 · 2 评论 -
C++程序静态链接
C++程序静态链接先看代码://simpleApp.cppint foo(int a, int b);int main(){ int a = 0; int b = 1; int c; c = foo(a, b); return c;}[root@xxxx] g++ -c simpleApp.cpp #生成.o文件[root@xxxx] g++ -o simpleApp simpleApp.cpp #生成可执行文原创 2021-05-29 16:24:14 · 373 阅读 · 1 评论 -
C++全局对象的构造与析构
C++全局对象构造与析构先上代码://simpleClass.cppclass A{ int val;public: A(int n){ val = n; } ~A(){ val = 0; }};A a1(1);int main(){ A a2(2); return 0;}抛出问题:局部对象a2和全局对象a1分别在何处调用构造函数和析构函数?将上述cpp文件编译成可一致性文件:g++ -o原创 2021-05-28 18:20:32 · 2145 阅读 · 5 评论 -
C++移动语义
C++移动语义可拷贝和可移动的概念在C++编程中,有的类是可以拷贝的,比如属性值、状态值等等,这些可以调用拷贝构造函数去拷贝。但有些类的对象是独一无二的,或者类的资源是独一无二的,比如申请的内存空间、IO buffer等等,他们不可以拷贝,但是可以把资源的所有权交出给新的对象,称为可以移动。C++11最重要的一个改进之一就是引入了move语义,这样在一些对象构造时就可以获取到已有的资源而不需要通过调用拷贝构造函数,申请新的内存,这样移动而非拷贝将会大幅度提升性能。例如有些右值即将析构,这时我们用移动构原创 2021-05-21 19:51:27 · 780 阅读 · 3 评论 -
C++对象初始化与重载赋值运算符
C++对象初始化与重载赋值运算符对象初始化如下代码:#include<iostream>#include<vector>#include<cstring>using namespace std;class A{public: int val; char *buffer; A(int n){ val = n; buffer = new char[val]; cout<<"A原创 2021-05-21 19:50:47 · 314 阅读 · 0 评论 -
C++STL容器扩容的效率问题
C++STL容器扩容的效率问题这里以STL中的vector容器举个例子,vector初始化时的容量是比较小的(在不使用reserve的情况下),当需要扩容时,需要把之前所有的元素都通过拷贝构造函数的方式拷贝到新的内存空间中,这样的效率是比较低的。看下面这段代码:#include<iostream>#include<vector>using namespace std;class A{public: int val; A(int n){原创 2020-10-14 18:52:58 · 561 阅读 · 0 评论 -
C++关于默认构造函数和无参构造函数
C++关于默认构造函数和无参构造函数默认构造函数在不提供任何构造函数的情况下,编译器给出一个不带参数的,不包含代码的构造函数。#include<iostream>using namespace std;class A{public: int val;};int main(){ A a; //这里调用的是默认构造函数 cout<<a.val<<endl; return 0;}当已经提供了显式的构造函数,例如:原创 2020-10-14 17:42:53 · 8096 阅读 · 4 评论 -
C++STL中resize()和reserve()的区别
C++STL中resize()和reserve()的区别简而言之,resize()会构造出新的元素,而reserve()只是为元素预留出空间而已。resize()#include<iostream>#include<vector>using namespace std;class A{public: int val;};int main(){ vector<A> vec; vec.resize(10); return原创 2020-10-14 17:41:34 · 816 阅读 · 0 评论 -
C++STL中emplace_back()和push_back()的区别
emplace_back()和push_back()的区别先来看几个例子:#include<iostream>using namespace std;class A{public: A(){ cout<<"A construct function."<<endl; } ~A(){ cout<<"A destory function."<<endl; }};int原创 2020-10-14 14:41:33 · 3802 阅读 · 2 评论 -
关于C和C++函数调用的参数传递问题(从x86-64汇编角度分析)
关于参数传递的问题:x86-64中有6个寄存器用于保存传入子函数的参数:寄存器参数%rdi第一个参数%rsi第二个参数%rdx第三个参数%rcx第四个参数%r8第五个参数%r9第六个参数超过6个以上的参数,需要被保存在调用者的函数栈帧中,通过%ebp的偏移值去获取。x86-64架构函数栈帧图如下图所示:图long func(long a, long b, long c, long d, long e, long原创 2020-09-13 17:31:29 · 1482 阅读 · 0 评论 -
引用动态链接库的原理
引用动态链接库的原理位置无关代码可以架在你而无需重定位的代码成为位置无关代码(Position-Independent Code,PIC)。用户对GCC使用-fpic选项指示GNU编译系统生成PIC代码。动态链接库的编译必须总是使用该选项。在x86-64系统中,对同一个目标模块中符号的引用是不需要特殊处理使之成为PIC。可以用PC相对寻址来编译这些引用,构造目标文件时由静态链接器重定位。然而...原创 2020-03-22 16:04:26 · 1342 阅读 · 0 评论 -
Linux静态链接
Linux静态链接简介什么是静态编译?静态编译就是编译器在编译可执行文件的时候,将可执行文件需要调用的对应动态链接库(.so)中的部分提取出来,链接到可执行文件中去,使可执行文件在运行的时候不依赖于动态链接库。这样做的优点是编译成功的可执行文件可以独立执行,而不需要再向外部要求读取函数库的内容。缺点是虽然可执行文件可以独立执行,但因为函数库是直接整合到可执行文件中,因此若函数库升级时,整个...原创 2020-03-21 16:40:16 · 824 阅读 · 0 评论 -
宏定义中的do{...}while(0);
宏定义中的do{…}while(0);我们都知道do while循环,但是在宏定义中常常会出现do{…}while(0);的用法,这样的循环不是只执行一次吗?不用do while也可以实现相同的功能呀,那么为什么要使用do{…}while(0);呢?我们先来分析几个例子:#define fun(x) func1(x);func2(x)if (true) fun(x);上述代码...原创 2020-03-17 09:54:23 · 1465 阅读 · 0 评论 -
Linux动态链接库
基本概念动态链接库(Dynamic Link Library)是一个共享函数库的可执行文件,它使进程可以调用不属于本身的可执行文件以及可以调用不属于本身的可执行代码中的函数。函数的可执行代码位于一个独立的动态链接库文件中,这样可以节省内存和磁盘空间,同时使得程序更易于升级。使用动态链接库的优点动态链接库在编译的时候,在程序里面只有一个“指向”的位置而已。也就是说,动态函数库的内容并没有整合到...原创 2020-03-15 12:48:59 · 468 阅读 · 0 评论 -
GCC参数介绍
gcc参数介绍-x language filename设定文件所使用的语言,而不是以后缀识别语言-x none filename关掉上个选项的语言设置,使用文件的后缀识别语言-c对文件进行预处理、编译和汇编,生成obj文件gcc -c hello.c-C在预处理的时候,不删除注释信息,一般用于分析程序-S只进行预处理和编译,生成汇编代码gcc -S hello.c...原创 2020-03-08 11:22:40 · 2024 阅读 · 0 评论 -
C++11 线程池简单实现
C++11 线程池简单实现以及测试话不多说,先上代码//threadpool.h#pragma once#include<vector>#include<queue>#include<thread>#include<iostream>#include<stdexcept>#include<condition_...原创 2020-03-04 17:38:37 · 258 阅读 · 0 评论