正常来说 shared_ptr 引用计数为0时会调用构造函数并释放内存,我们可以自定义一个删除器,来代替这个过程删除器的参数为对应类型的指针变量, 传递给shared_ptr构造函数的第二个参数示例默认#include <iostream> #include <memory> using namespace std; class Test { public: ~Test() { cout << "析构" << endl; } }; int main() { shared_ptr<Test> p(new Test); return 0; } // 输出 析构函数指针#include <iostream> #include <memory> using namespace std; class Test { public: ~Test() { cout << "析构" << endl; } }; vo
chrono 是 C++ 标准库中的一个命名空间,包含了一组用于处理时间和时间相关操作的类和函数头文件#include <chrono>基本组成Durations(时间段)用来表示一个时间段, duration类是一个模板类,它的模板定义如下template <class Rep, class Period = std::ratio<1>> class duration;Rep 为一种数值类型,duration用这个类型来表示 Period 的数量,比如int float doublePeriod 表示用秒表示时间单位的类型, ratio 这个类用来表示一个比例, 有两个参数,第一个为分zi,第二个为分母, 第二个默认值为 1, 比如 ratio<1, 1> 就代表一秒, ratio<60, 1> 就代表一分钟, ratio<1, 1000>代表一毫秒。常用的duration也可以使用预设好的如下,都是 预设好参数的 的 duration 类:第一个参数使用的long long, 所以表示的是整数。例如std::
在执行 git push -u origin main:main 时出现了以下错误git push -u origin main:mainerror: src refspec main does not match anyerror: failed to push some refs to 'https://github.com/yhy0816/networkDiskServer.git'原因 仓库刚刚创建,还没有提交过,此时main分支还没有真正创建, 导致 push 的时候找不到本地分支解决 提交一次,再次pushgit add . git commit -m "..." git push -u origin mian
用位来表示一个数,它是一种类似数组的结构,它的每一个元素只能是0或1,每个元素仅用1bit空间。头文件:#include<bitset>定义bitset<size> bs(initNum)其中 size 为 bitset 的容量,initNum 为初始值, 是转化为size长度二进制后赋给c的所有位, 还可以用01字符串来初始化,默认初始化为全0访问可以使用 [] 来访问,例如 bs[1] = 1; , 注意, 非0值会赋值成1, 0值赋值为0常用成员函数c.size() // 返回大小(位数) c.count() // 返回1的个数 c.any() // 返回是否有1 c.none() // 返回是否没有1 c.set() // 全都变成1 c.set(p) // 将第p + 1位变成1 c.set(p, x) // 将第p + 1位变成x c.reset() // 全都变成0 c.reset(p) // 将第p + 1位变成0 c.flip() // 全都取反 c.f
原生数组使用起来有很多不方便,比如将数组作为参数传递,数组会退化为指针,必须再传递一个长度等C++11引入了array容器来代替内置数组。std::array除了有内置数组,它支持随机访问、效率高、存储大小固定等特点外,还支持迭代器访问、获取容量、获得原始指针等功能使用头文件 定义std::array<int, 5> a0 = {0, 1, 2, 3, 4};其中模板的第一个参数是类型, 第二个参数是数组的长度, 长度不可以是变量,可以使字面量或常量。可以使用{}来直接初始化,也可以使用另外的array来构造,但不可以使用内置数组来构造。访问元素它提供了 []、at、front、back、data 这几个函数来访问元素, data是用来获取第 0 个元素的地址, 也就是数组首地址;和别的容器一样,array也可以使用迭代器访问,begin(), rbegin(), end(), rend();获取sizearray传递给函数时不会退化为指针, 可以直接通过 size()成员函数获取数组的大小;成员函数empty 检查容器是否为空 size 返回容纳的元素数
对于某种需要特殊处理的模板参数, 可以使用模板特化模板特化是为模板提供特殊版本的一种机制。这个特殊版本仅适用于特定的模板参数。使用场景当某个特定类型需要不同的处理逻辑时。优化:为特定类型提供更高效的算法。注意事项特化版本不能独立于原始模板存在。不能有多个相同的特化版本。template<typename T> class Test { void fun(T arg) { cout << "fun(T arg)" << endl; } }; template<> class Test<int> { // 为 Test 类提供了一个 int 特化的版本 当模板参数为int时 会使用这个实现 void fun(int arg) { cout << "fun(int arg)" << endl; } };模板偏特化是在模板的某些参数已经确定的情况下,为剩余参数提供一个特殊实现。使用场景当只有某几个模
类成员函数指针在 QT 中当我们要连接一个重载的信号和槽函数时, 直接对成员函数取地址无法确定调用的是哪个函数, 这时候可以使用类成员函数指针来接收成员函数地址, 同过函数指针的类型来确定调用的是哪个函数。语法:定义返回值类型 (类名:: * 指针名) (参数列表) = &类名::函数名通过 等号左侧的 返回值类型 + 参数列表 就可区分调用的是哪个函数, 然后就可以传给 connnect 函数了调用(类对象.*指针名)(参数列表);(类对象指针->*指针名)(参数列表);这里的前面一对括号是很重要的,因为()的优先级高于成员操作符指针的优先级。指向类数据成员的指针和类成员函数指针类似, 不过它指向的是类的成员变量, 要注意的是成员变量指针作为一个变量,在底层实现上,存放的是对象的数据成员相对于对象首地址的偏移量,通过成员变量指针访问成员变量时需要提供对象的首地址,即通过对象来访问。语法:定义成员类型 类名::*pointer = &类名::成员变量名访问类对象.*指针名类对象指针->*指针名;总结使用 ::* 声明一个成员指针类型,或者定义一个成员指针变量
先看一个示例int main() { const int CONST_NUM = 10; int* p = const_cast<int*>(&CONST_NUM); *p = 20; cout << "CONST_NUM = " << CONST_NUM << endl; cout << "*p = " << *p << endl; } 在代码中我们是这样一个流程首先声明了一个局部常量 const int CONST_NUM = 10;然后通过 const_cast 去除了指向 CONST_NUM 的指针的常量属性 接着通过指针 p 对 CONST_NUM 进行了修改最后输出了 CONST_NUM 和 *p 的值我们来看一下输出结果CONST_NUM = 10 *p = 20 CONST_NUM 的 值居然和 *p 是不同的, 这是什么原因呢其实是c++ 存在 const 优化, 在 c 语言中没有
C++引入了四种更加安全的强制类型转换运算符,分别是const_cast、static_cast、reinterpret_cast和dynamic_cast,作用和区别如下:const_cast: 去除const(volatile)属性, 只针对指针、引用和this指针有效,其他情况会报错示例int main() { const int a = 0; // int *p = &a; // 这样会报错 int *p = const_cast<int*>(&a); // 去除了 const 属性 // int c = const_cast<int>(a); // 报错,因为只针对指针、引用和this指针有效 return 0; }static_cast:用于各种隐式转换例如void* 转换为任意类型的指针任意类型的指针转换为void*编译器允许的跨类型转换,比如char类型转换为int类型,double转int型static_cast 不做类型检查, 允许子类类型的指针安全转换为父类类型的指针,相反也能转换能成功但是不安全,结果未知,只能在拥有继承
C++11引入了强大的线程库 std::thread,相比于Linux下的pthread要方便许多。头文件<thread>使用方法先来一个示例#include <thread> #include <iostream> using namespace std; void t() { cout << "t() Hello World" << endl; } int main() { thread t1([]() { cout << "lambda Hello World" << endl; }); thread t2(t); t1.join(); t2.join(); } 这段代码的作用就是创建两个线程,并在主线程内等待他们结束thread这个类的构造函数可以接受一个函数指针或者lambda表达式,当我们thread类的对象创建,就会创建线程来执行我们传入的函数或lambda表达式。这个线程对象
lelele