
C++ 基础
文章平均质量分 56
一些C++基础知识
s.feng
计算机视觉,C++
展开
-
static_cast
如果自定义类型A,想让其他类型转成A, 就在A中定义构造函数,如果想转成别人就定义一个operator。原创 2025-03-19 14:25:31 · 128 阅读 · 0 评论 -
右值引用使用说明
可以看到唯一的区别就是,一个调用了移动构造函数(这个性能会好很多),一个调用了copy构造函数,对于BaseClass而言,基本都是如下实现, 其实核心就是交接堆区域的内存,由于左值引用只能针对已经存在的对象,对于没有持久化地址、通常是临时对象、字面量、或在表达式中求值之后不再需要的对象无法使用,右值引用就是做这个事情的。比如一个函数的返回值是Type&& foo()这就代表了返回的是一个右值。比如一个函数foo(Type&& par)原创 2024-12-10 15:48:56 · 184 阅读 · 0 评论 -
union不能被初始化由于有 non-trivial构造函数
如果类的成员是具有上述非平凡构造函数、析构函数或赋值操作符的类,则该成员也被认为是非平凡的。换句话说,如果一个类包含非平凡成员对象,那么这个类的构造函数、析构函数或赋值操作符也将是非平凡的。其实在union中的成员函数nt, 虽然是非平凡成员,但是构造函数和析构函数都有,为啥union不能直接调用相关函数生成一个默认的构造函数和析构函数呢?赋值操作符用于将一个对象的值赋给另一个对象。如果一个类从虚基类继承,那么这个类的构造函数、析构函数和赋值操作符也会变成非平凡的,因为需要处理虚基类的初始化和清理。原创 2024-08-27 17:44:26 · 1102 阅读 · 0 评论 -
C++对象初始化
以后要养成用大括号初始化的习惯,不然一堆坑!(这里推荐A a{1}, 而不是A a={1}, 两者还是有一些区别的,后续遇到问题再补充吧)原创 2024-08-22 17:50:27 · 308 阅读 · 0 评论 -
unique_ptr使用说明
指针问题一直是一个比较麻烦的事情,比如很多人说要用智能指针完全替换掉裸指针,有人说要用unique_ptr, 有人建议shared_ptr,可是实际看各种经典框架,发现一个框架什么指针都有,使用的方法也是无法八门,这里简单说一下unique_ptr的使用场景和注意事项。unique_ptr核心目的是:1.所有权唯一。2.避免所有人忘记delete。但凡符合这两个要求就可以建议使用unique_ptr。原创 2024-03-12 15:22:30 · 451 阅读 · 0 评论 -
C++中的static和hidden
动态库。原创 2024-02-05 22:00:52 · 565 阅读 · 0 评论 -
realname,soname和linkname
其实soname设置为A.so也是可以的,这样的话,如果我更新为11的大版本后,理论上厂家A还是可以运行可执行文件,但是我版本变动太大,A在实际生产中会报错,为了把风险控制在可执行文件启动前,所以可执行文件的soname最好有版本号,这样程序会启动失败,提醒你却是版本10的so。当我发布一个动态库的时候,比如版本是maj.min.patch(10.2.1)的格式,当我改了小版本的号的时候(10.3.1),如果厂家A用的是我写的库,他需要做什么?原创 2023-11-26 23:16:28 · 535 阅读 · 0 评论 -
如何禁止在堆上和栈上创建对象
因为new一个对象会调用operator new函数。所以把这个函数设置为private就可以了。设置成protected, 目的是继承时的时候好调用。原创 2023-10-17 23:24:50 · 187 阅读 · 0 评论 -
抽象类与虚基类
发生继承过程中,A:virtual public B。类中包含纯虚函数就是抽象类。原创 2023-10-13 16:29:13 · 83 阅读 · 0 评论 -
C++函数名与类型
假如上面的函数编译通过的话,下面调用就会出现歧义,为此c++对于函数名而言拒绝使用返回值,一个函数的名字就是, 有些语言支持函数返回值不同的函数,但是在调用的时候就不支持上述写法了。下面我们用is_same做一个实验可以看出来。原创 2023-10-12 10:30:26 · 210 阅读 · 0 评论 -
编译器自动生成的构造函数
我们根据上面已经知道,编译器会自动生成构造函数,但是如果程序员自己提供了构造函数怎么处理?string A;Student B;Teacher C;int e;Test()补充初始化列表Test()//编译器会报错:成员变量**对象**(不是基础数据)必须在构造函数初始化列表里初始化挪到函数中Test()A(),B();C();// 等效于:tmp("student"), B=tmp;原创 2023-09-25 14:01:14 · 217 阅读 · 0 评论 -
.inl文件
内联函数通常在C++头文件中实现,但是当C++头文件中内联函数过多的情况下,我们想使头文件看起来简洁点,能不能像普通函数那样将内联函数声明和函数定义放在头文件和实现文件中呢?最近工作涉及到thrust库,看了半天也没找到一个头文件的函数定义,本来以为会有一个cpp源文件对应h头文件,后来问头文件的末尾发现了一个include,所以有必要了解这个文件组织形式。由于编译器不支持将模板的声明与实现分开编译,但是有了inl文件,我们可以把声明放在头文件中,然后将具体实现放在inl文件中。原创 2023-09-08 15:41:15 · 785 阅读 · 0 评论 -
C++全局变量
工程全局变量声明方式是头文件中extern 来声明, 原因是如果放在global.h中定义的话,就会出现global.obj和other.obj定义冲突的问题。// 如果不加extern默认是extern, 这里要有良好的编程习惯,不要用默认,该写出来就要写出来 extern double * ptr;编译单元全局变量。原创 2023-05-07 14:41:49 · 1979 阅读 · 0 评论 -
C++ function的作用
【代码】C++ function的作用。原创 2023-04-09 20:21:48 · 154 阅读 · 0 评论 -
gdb相关知识
代表编译路径,可以打个断点,然后用info source命令查看。代表当下调试的目录,直接用pwd就可以。原创 2023-01-12 20:57:47 · 753 阅读 · 0 评论 -
#pragma unroll的作用
比如每次i的初始化,每次做一个判断,还有i++的计算,一旦展开后全部没有了,第二就是当循环里有load数据和计算数据的话,展开后可以让这两个pipe并行执行,隐藏延迟。需要N是常量,不然编译器不认识,没法展开,这个在CPU和GPU上优化都是通用的,再说一次他是。原创 2022-11-06 23:56:28 · 678 阅读 · 0 评论 -
boost::Variant的相关说明
简单说继承一般是解决子类的个数不固定,但是子类接口函数是固定的的情况,而访问者模式是解决子类的个数是固定的,但是子类接口函数是不固定的情况。这里我们的variant的类型个数在初始化的时候就确定的,所以可以利用访问者模式添加不同的接口函数。简单理解就是这个variant可以承接其申明类型中的任意一个,而且表现对外时也只能是其中的某一个类型。可以看到,这里不需要继承一个公共接口的基类,各写各的,这样也没有虚函数表和虚函数指针。在解释使用场景之前,先需要了解访问者模式,这可以参考这篇。Variant是什么?原创 2022-10-31 13:21:47 · 598 阅读 · 0 评论 -
bind()函数和thread()
当调用函数对象g时候,函数对象g会调用function函数,并把其参数传给function函数,g的第一个参数会传给function的持有占位符_1的位置,即arg5。第二个参数会传给function的持有占位符_2的位置,即arg3。当调用新的函数对象时,新函数对象会调用被调用函数,并且其参数会传递到被调用函数参数列表中持有与新函数对象中位置对应的占位符。上面这段代码可以理解为,利用Add函数生成一个新的函数NewAdd,NewAdd的参数有一个,会在调用Add时候把参数放到_1的占位符的地方。原创 2022-09-30 20:41:33 · 603 阅读 · 0 评论 -
C++中的通俗理解左值,右值,左值引用,右值引用
move的意思是把左值的名字移出掉(其实还是可以用a去调用),所以会变成右值,因此一个左值一旦用了move, 最好保证它在move后不要再被调用,毕竟move的思想就是把名字除去了,毕竟都被除名了,也就是想表达以后我不会再叫你a了。会编译报错,为什么?因为a是一个左值,a *2 这里是利用了a的右值属性,所以a *2 会生成一个没有名字的右值,你去给一个没有名字的内存块取别名是不行的,因为他都没有名字,何来别名一说?因为a是一个左值,而&&是给右值起第一个名字,你都有名字了还来用&&凑热闹,所以编译报错。原创 2022-09-28 20:23:46 · 672 阅读 · 1 评论 -
pkg-config的简单用法
最近在开发C++的时候遇到了一个pkg-config的命令,使用方法类似于『g++ test.cc -o test `pkg-config --cflags --libs protobuf`』,比如这里依赖protobuf这个库,那么直接利用上面的命令就可以编译成功了,很神奇,不用指定include 和 libs就可以完成。原创 2022-09-18 13:30:43 · 1432 阅读 · 0 评论 -
C++中的 RTTI
RTTI(Run-Time Type Identificatio)翻译为汉语是运行时类型识别,顾名思义就是在运行的时候识别出来对象的类型,它使程序能够获取由基指针或引用所指向的对象的实际派生类型。在C++中,为了支持RTTI提供了两个操作符:dynamic_cast和typeid。根据上面代码可以看到,只有对包含虚函数的基类才有效果。原创 2022-09-14 23:37:22 · 385 阅读 · 0 评论 -
static变量和全局变量的区别
可以看到,静态全局变量只能用在当前文件中,全局变量除了本地文件,其他文件也可以通过extern来获得使用。对于静态局部变量的来说,作用域只能在定义的那个函数里,而且在编译的时候就会分配地址,而且只会初始化一次,即使每次函数调用的时候都会走到初始化这一行,实际上并不会执行。...原创 2022-07-21 12:48:27 · 1000 阅读 · 0 评论 -
为什么函数模板没有偏特化?
C++里的类没有重载,类模板也没有重载,函数有重载,函数模板也有重载,这个结论是符合常理的。参考:http://www.gotw.ca/publications/mill17.htm原创 2022-06-27 10:43:48 · 1365 阅读 · 1 评论 -
类中的何时使用原始,unique_ptr, shared_ptr?
在看很多框架的时候,经常可以看到定义的类中有类指针成员变量,但是使用的五花八门,实际自己设计类的时候不知道该使用原始指针,unique_ptr, 还是shared_ptr, 根据下面这位大佬的解释,基本有个初步感觉,下面是具体的说明。ptr_1: 该对象由Student之外逻辑去new和delete, 只要在用的时候对象存在就行。ptr_2: 该对象由Student之外逻辑去new,执行的时候交给Student去处理,Student对象结束的时候,会自动delete掉。ptr_3:该对象由Studen原创 2022-06-14 21:05:46 · 647 阅读 · 0 评论 -
dlopen和 dlsym的使用方式
背景为了是不同的逻辑解耦,一般会把各个业务封装成动态库,然后主逻辑去调用各个插件。demo生产动态库int add(int a,int b){ return (a + b);}int sub(int a, int b){ return (a - b);}gcc -fPIC -shared caculate.c -o libcaculate.so调用dlopen#include <dlfcn.h>void *dlopen(const char *原创 2022-03-26 18:30:28 · 2134 阅读 · 0 评论 -
C++ 偏特化
定义偏特化包含两种:个数类型demo个数偏特化:template<typename First, typename Second>struct Test{ typedef First type_value;}原创 2022-03-13 15:16:20 · 2444 阅读 · 0 评论 -
C++符号解析
在代码进行连接的时候,经常找不到某个函数,不过由于c++做了一些修饰,所以很多时候不大清楚这个字符串到底代表什么,下面是一位大神给的解释:地址GCC的基本C++名称修饰方法如下:所有的符号都以"_Z"开头,对于嵌套的名字(在名称空间或在类里面的),后面紧跟"N",然后是各个名称空间和类的名字,每个名字前是名字字符串长度,再以"E"结尾。比如N::C::func经过名称修饰以后就是_ZN1N1C4funcE。对于一个函数来说,它的参数列表紧跟在"E"后面,对于int类型来说,就是字母"i"。所以整个N::原创 2022-03-08 23:13:08 · 1980 阅读 · 0 评论 -
元编程中的顺序、分支、循环
文章目录顺序执行分支执行std::conditional特化std::enable_if循环顺序执行template<typename T>struct remove_ref_const{private: using inter_type = typename std::remove_reference<T>::type;public: using type = typename std::remove_const<inter_type>::type;}原创 2022-03-07 20:10:05 · 599 阅读 · 0 评论 -
C++模板元编程
元函数一种函数,输入一个东西,输出一个东西,就是一种映射类型元函数输入一种类型,返回出一种类型。//函数定义template<typename T>class FunType<T>{ using type = T;}template<>class FunType<int>{ using type = char;}template<>class FunType<float>{ using type =原创 2022-03-04 20:26:43 · 962 阅读 · 0 评论 -
c++的常量折叠
开会的时候听到一耳朵,不知道是啥,查了一下感觉还挺有意思的,以前也没注意过。例子#include "stdio.h"#define PI 3.14int main(){ double pi = PI; const int i = 0; int *j = (int *) &i; *j = 1; printf("0x%p\n0x%p\n%d\n%d\n",&i,j,i,*j); //观看实原创 2021-11-11 14:34:47 · 559 阅读 · 0 评论 -
C++可变模版参数
模板变参是C++11中引入的一个新特性,具体如下:原创 2021-09-30 10:46:42 · 409 阅读 · 0 评论 -
C++内存碎片
什么是内存碎片?在一个进程中不能被重复使用的内存块就是内存碎片allocator中所产生的内存碎片具体可以参考《STL源码剖析》中的解释,比如pool中的剩余量是22个字节,而下一次需要32个字节,这就要重新malloc,那么这22个字节就是无法使用,也就是说形成了内存碎片。malloc所产生的内存碎片当调用malloc()的时候,其实会调用系统的api,举例linux:void* malloc(size_t size){ if(size<128kb) { brk(); }原创 2021-09-20 23:32:52 · 1314 阅读 · 0 评论 -
C++虚函数返回值类型
最近在看paddle的库代码时候发现一个问题,简单的代码如下:#include <iostream>using namespace std;class One{public: virtual One* show() { std::cout<<"1"<<std::endl; return this ; };};class Two: public O原创 2021-09-12 17:46:43 · 3531 阅读 · 1 评论 -
二、allocator的实现原理
以下内容主要是根据侯捷老师的教学视频所总结的:最原始的写法#inclide<cstddef>#include<iostream>using namespace std;class First {public: First(int x):i(x){}; void* operator new(size_t); //注意啊,这个地方其实有个问题, //理论来说要先有对象才能调用这个函数,这就很不合理,我在new的时 //侯压根还没对象呢。原创 2021-09-09 20:56:56 · 296 阅读 · 0 评论 -
一、内存构造
newnew的流程是:void* p = ::operator new()// 分配内存((TYPE*)p)->construct()//调用构造函数return p //返回pdeletedelete的流程是:§->destruct()void* p = ::operator delete()我们能改的地方只有operator new/delete, 这个是自己可以改写的。原始::operator new/delete()原始的operator new就是在里面调原创 2021-09-09 10:51:44 · 182 阅读 · 0 评论 -
史上最全面的ps-lite理解
概述ps-lite是一个分布式参数服务器,具体什么是分布式,什么是参数服务器就不在此详述,talk is cheap, show me code。代码既然是分布式,那么我们就来看看整个框架有哪几部分。可以看到有worker, server, scheduler.scheduler node环境配置export DMLC_NUM_SERVER=2export DMLC_NUM_WORKER=2export DMLC_PS_ROOT_URI='127.0.0.1'export DMLC_P原创 2021-04-22 19:57:25 · 1723 阅读 · 0 评论 -
内存对齐问题
背景内存对齐可能很多程序员接触不到,也许只在面试的偶尔会被问到过,但是也只是背背固定的公式,大概知道怎么计算,也能知道大致的原理,就是数据不对齐,取数次数要变多,但是只是理解到这种程度还不够,目前intel cpu不需要对齐才能访问,但是对于一些新的arm芯片,自研芯片等等,自己在做hpc时,发现这个内存对齐问题还是一个比较严重的事情,这里好好的捋顺一下,避免自己以后遗忘。规则结构体中大小为 size 的字段,他的结构内偏移 offset 需要是其min(default, size)的整数倍 //d原创 2021-04-19 10:28:09 · 1407 阅读 · 2 评论 -
排序算法-C++版本
排序算法概述快速排序谢尔排序选择排序堆排序冒泡排序归并排序插入排序概述排序算法记得是数据结构与算法第一个要掌握的,作为一个合格的程序猿,理论来说应该是信手拈来的,可是扪心自问好像自己一直掌握的也不是很扎实,不管是在面试还是平时做题,每次遇到还是心里会有咯噔一下的感觉,一旦有胆怯的感觉就说明还是不够扎实,反反复复也练习很多次都忘,所以这里简单总结一下,供自己和大家复习使用。快速排序谢尔排序选择排序堆排序堆排序相对于其他算法,估计能一把写出来的不多,但是其实堆排序并不难,主要是理解透彻,记忆一些点原创 2021-01-26 10:30:34 · 338 阅读 · 0 评论 -
C++条件变量
文章目录基本介绍虚假唤醒结论参考基本介绍在多线程编程中有一个条件变量,在头文件中condition_variable,常用在设计线程池的时候使用,该条件变量需要配合mutex才能使用std::mutex mtx;std::condition_variable cv;void print_id (int id) { std::unique_lock<std::mutex> lck(mtx);// mutex会使用lck.lock(),其他线程会卡在这一句; cv.wait(原创 2020-09-12 10:17:41 · 1992 阅读 · 0 评论 -
C++中的move特性
C++ 11中出现了move函数,自己平时几乎没使用过,不过看很多源码都有move的使用,而且在看《代码整洁之道》《c++性能优化指南》等书籍的时候都对该函数有推荐,不过这其中涉及到了其他的知识,比如左值,右值得概念,所以一直也没空对其进行梳理总结,下面是一点自己看书的理解:std::move并不会移动任何内存,它的功能是将一个左值类型强制转化为右值引用类型。简单说说就是std::move等同于实现一个类型转换:static_cast<T&&>(T 左值);至于左值,右值,左原创 2020-08-13 14:25:34 · 1262 阅读 · 0 评论