
C++
vegetablesssss
一只菜鸟。
展开
-
多态中虚函数调用问题
原因是父类对象尚未创建完成,因此虚函数机制(即虚表的分派)并没有完全生效。虚函数的分派机制依赖于对象的完整类型,而在构造函数阶段,C++ 认为对象的类型是父类类型。在多态中,一般通过虚函数表会调用子类重写的虚函数,然而,有一种情况调用的还是父类的虚函数,就是在父类的构造函数中调用的是父类的虚函数,无论子类是否重写。原创 2024-12-21 15:54:31 · 204 阅读 · 0 评论 -
std::funture和std::promise
在线程池中获取线程执行函数的返回值时,通常使用 std::future 而不是 std::promise 来传递返回值。这是因为线程池内部已经管理了任务的执行和结果的传递,你只需要将任务提交给线程池,并使用 std::future 来获取结果。线程池内部一般会使用一个任务队列来存储待执行的任务,并使用一个线程池管理器来调度任务的执行。当你向线程池提交任务时,线程池会选择一个空闲的线程来执行任务,并将结果存储在与任务关联的 std::future 对象中。原创 2024-05-16 13:26:26 · 369 阅读 · 0 评论 -
zip解压缩
使用unzip库可以轻松解压zip文件,源码下载地址:http://www.codeproject.com/Articles/7530/Zip-Utils-clean-elegant-simple-C-Win。SetCurrentDirectory:设置解压目录。原创 2024-02-19 15:09:33 · 469 阅读 · 0 评论 -
C++动态调用dll中的函数
1.dll中的函数声明必须写上extern “C” __declspec(dllexport),不然找不到该函数。2.dll文件和exe放在同一文件夹下。原创 2023-11-17 10:29:34 · 410 阅读 · 0 评论 -
vector源码剖析
在push_back函数中,data[size++] = value调用的是=赋值函数,std调用的是拷贝构造,可以替换为以下代码既可以实现。上面是vector的简单实现,reserve函数中,operator new和new operator可以查看。输出:构造函数 拷贝构造。原创 2023-07-28 14:32:28 · 236 阅读 · 0 评论 -
std::thread和std::mutex
创建了一个名为t1的线程,调用join方法阻塞等待线程退出,也可以调用detach使线程处于游离态,参考,可以观察到,必须调用这两个方法中的一个,不然会报错:当thread对象被创建时,会给线程分配一个线程id(不为0),join和detach函数每次执行时会将_Thr对象置空,也就是将线程id置为0,当thread对象析构时,调用joinable函数发现线程id不为0就会terminate终止程序。原创 2023-07-12 17:21:16 · 257 阅读 · 0 评论 -
C++虚函数表
因为类中所有的虚函数地址都是在编译时期存放在虚函数表中,虚函数的调用必须通过虚函数表,而要想找到虚函数表必须通过虚指针vptr,而虚指针vptr只有在对象创建后才存在。可以看到pa和a都有一个名为_vfptr的成员并且他们的值相等,其类型为void**,这个就是我们常说的虚指针vptr,它指向虚函数表,虚函数表存放的即是类中的每个虚函数的地址,即_vptr下的[0][1][2],分别为类A三个虚函数的指针。2.虚函数表不属于类,在编译时期创建,为每个含有虚函数的类分配一个虚函数表。原创 2023-07-12 10:35:59 · 129 阅读 · 0 评论 -
创建对象加不加括号区别
i ++;} };A fun();//这种情况只是声明了一个函数,并没有创建对象 A a;return 0;以上结果均输出输出-842150451,没有对m_a进行初始化。i ++;} };A fun();A a;return 0;以上结果均输出100。原创 2023-07-10 15:23:07 · 258 阅读 · 0 评论 -
extern,全局变量,静态全局变量
在a.h中使用extern声明一个全局变量a,a.cpp中定义全局变量a,在main.cpp中无须包含a.h头文件,使用extern声明一下变量a即可找到a.cpp中的变量a,当然直接包含a.h头文件也可以,不过包含的东西会过多。static修饰的变量只能在本文件内使用,而extern修饰的变量可以在其他文件内使用,其他文件想使用static修饰的变量必须包含其头文件。2.静态全局变量表示其只能在本文件内使用,其他文件想使用必须包含其头文件。1.extern声明的全局变量表示其可以在其他文件内使用。原创 2023-04-14 14:28:49 · 515 阅读 · 1 评论 -
VS2022调试vector无法显示详细信息
为了显示vector大小以及详细的元素,需要编写natvis文件。原创 2023-03-03 12:11:44 · 2551 阅读 · 3 评论 -
vector细节
往vector中push元素,当超过vector的容量时,vector重新申请一块内存更大的空间,将原来的内存拷贝过来,然后释放掉原来的内存空间,为了省去内存释放的开销,可以先调用reserve函数申请足够的容量。原创 2022-11-22 14:34:34 · 132 阅读 · 0 评论 -
git使用详解(fetch pull pick等)
选择pick即可将oem_hlzq修改信息合并到自己分支上,然后提merge即可合并到master分支上。remote branch选择master,即可将master上的代码拉到自己的分支上。原创 2022-08-17 14:48:45 · 1329 阅读 · 0 评论 -
dllexport和dllimport
在VS中,如果要跨项目使用类或变量,就必须用到dllexport和dllimport,下面分别举例全局变量,函数和类跨项目使用。环境准备:使用VS分别新建一个windows应用程序和DLL项目,windows应用程序项目名称为ConsoleApplication1,DLL项目名称为testExtern。在ConsoleApplication1上右键项目属性附加库目录加上testExtern生成dll和lib所在的目录附加依赖项加上testExtern.lib名称在同一个项目中,全局变量不需要原创 2022-07-01 10:28:30 · 2008 阅读 · 0 评论 -
VS正在加载符号导致程序启动变慢
每次debug时程序启动都特别慢,需要等个五分钟左右程序才启动起来。去掉Microsoft符号服务器勾选即可解决这个问题,不去请求microsoft符号服务器,应该是去请求缓存目录下的符号了,因此加载起来特别快。...原创 2022-06-20 15:11:23 · 2011 阅读 · 0 评论 -
C++代理类作用
C++代理类可以帮助我们实现想要得效果,例如:1.多维数组2.区分左值和右值(区分读和写)3.压制隐式转换想要实现一个二维数组类,重载[][]肯定是不行的 ,无法通过编译,这时就可以通过代理类来实现:区分读和写=左边为写,右边为读,但是如果重载[]并不能区分是读还是写,对于非常量对象,不管是读还是写,调用的都是非常量的重载的[]函数,这时候就要使用代理类,不直接返回字符,而是返回一个代理类对象,在代理类中重载=即可区分读和写。—more effective C++ 条款30压制隐式转换使用M原创 2022-06-15 10:46:52 · 333 阅读 · 0 评论 -
C++操作符重载细节
1、C++不能重载的操作符有下面5个:?: . :: sizeof .*2、区分前置和后置++运算class MyInt{public: MyInt(int m=0) :m_i(m) {} MyInt& operator++() //返回引用是因为可以支持前置++++这种形式 { ++m_i; return *this; } const MyInt operator++(int) //带有参数的为后置运算符,返回const禁止后置++++形式 { MyI原创 2022-05-13 10:34:16 · 333 阅读 · 0 评论 -
new operator和operator new
new operator有时会碰到一些面试题:请说明new operator和operator new之间的差异?在堆内存上申请一块string空间,我们通常会这样写:string *ps = new string("ss");上面使用的是new operator,它的动作有两个含义:1.在堆中分配足够多的空间来放置对象2.调用构造函数,为对象设定初值事实上,在第一步中new operator调用了operator new来分配内存空间,函数operator new通常声明如下:void原创 2022-05-10 10:56:07 · 541 阅读 · 0 评论 -
析构函数调用时机
1、对象正常状态下被销毁,栈对象离开了他的生存空间,堆对象调用delete。2、当对象被异常处理机制,也就是异常传播过程中的栈展开机制被销毁。下面详细讲讲栈展开: 当一个函数被调用的时候,系统会开辟一个栈帧给它,如果该函数抛出异常,那么该函数的栈帧就会被销毁,有catch语句就捕获异常进行处理,没有catch语句就继续往调用他的函数抛,像这样一直抛的过程称为栈展开。 在栈展开的过程中,抛出异常前的内存都会被自动释放,注意,如果是在堆中开辟了内存,而delete语句是在异常抛出之后,那么就会造成内原创 2022-03-28 10:46:28 · 1603 阅读 · 0 评论 -
push_back和emplace_back区别
在使用vector容器时,往容器里添加元素时,有push_back和emplace_back两种方法,一般用得最多得是push_back,下面看看这两种方法得区别:push_back源码,有重载得左值和右值,关于左值和右值可以查看右值引用、移动构造函数和movevoid push_back(value_type&& _Val){ // insert by moving into element at end if (_Inside(_STD addressof(_Val))) {原创 2022-03-13 20:52:08 · 13705 阅读 · 2 评论 -
C++模板特化
在C++中,模板在代码重构方面起着重要作用,由于之前对模板一直不熟悉,现在总结一下有关模板特化的使用。1.通过template<>实现特化,可以重写方法的实现class Sparrow;class Swallow;class Turtledove;template<class T>class Fly{public: static void funFly() { cout << "fly" << endl; }};templat原创 2022-02-09 15:44:20 · 633 阅读 · 0 评论 -
栈溢出原理
栈是用来存储程序的局部变量的,一般来说,栈的大小也就几兆,当局部变量的大小超过了栈的大小,就会发生栈溢出。场景1:局部变量大小超过栈大小int main(){ int a[1024*1024*8]; return 0;} 运行上面这个程序,发现:报错:Stack overflow场景2:递归层次过深void test(){ static int i = 0; cout << i++ << endl; test();}int main(){ t原创 2022-01-27 14:12:09 · 651 阅读 · 0 评论 -
C++内存泄漏检测
下载安装VLD(Visual Leak Detector),链接:https://pan.baidu.com/s/1HpahasT3m-nybfOZhZgkNw?pwd=7g5d提取码:7g5d我这里使用的是VS2015,默认安装即可。#include "vld.h"using namespace std;void test(){ char *a = new char[1000];}int main(){ test(); return 0;} 上述代码中test()函数存原创 2022-01-18 09:51:00 · 716 阅读 · 0 评论 -
VS跨进程调试
当程序中一个进程启动另一个进程时,在VS中直接打断点是无法进行调试得,通过以下方法调试另一个进程。任务管理器中找到要调试得进程,右键调试选择VS进行调试即可打开VS后,将要调试得文件拖进去即可进行调试...原创 2021-11-30 09:24:32 · 626 阅读 · 0 评论 -
make_shared剖析
引言关于make_shared,大家都知道可以用它来初始化shared_ptr:shared_ptr<string> sp = make_shared<string>();那为何要使用它呢,我们都知道,也可以直接通过shared_ptr的构造函数来生成shared_ptr对象:shared_ptr<string> sp1(new string());这两者有何区别呢?首先来看看make_shared源码:make_shared源码template<原创 2021-11-13 11:37:01 · 6149 阅读 · 3 评论 -
VS2019右键项目属性常用配置
修改上面三个配置即可打断点调试原创 2021-10-14 17:30:10 · 967 阅读 · 0 评论 -
智能指针线程安全问题
引言有关智能指针实现原理可以参考:智能指针实现原理,其中shared_ptr包括一个实际数据指针和一个引用计数指针,这两个操作不是一个指令可以完成的,因此多线程环境下,势必有问题。原创 2021-10-12 10:47:39 · 972 阅读 · 0 评论 -
[]和at的区别
vectorstd::vector<int> v;v.push_back(1);int b = v[3];int c = v.at(3);程序执行到v[3]时:程序执行到at(3)时:一个是直接崩溃,一个抛出异常,抛出异常可以捕获异常:std::vector<int> v;v.push_back(1);//int b = v[3];try{ int c = v.at(3); }catch (const std::out_of_range&原创 2021-10-01 10:56:51 · 1012 阅读 · 0 评论 -
STL中sort算法
stl中的sort算法接收三个参数,分别是首迭代器,尾迭代器和比较函数对象,最后一个参数可以省略,默认从小到大比较。需要注意的是它所接收的迭代器是RadomAccessIterator,也就是随机迭代器,支持it+n这种,像list就不支持,不过list又自己的成员函数sort可以使用。struct Cmp{ bool operator()(int i1, int i2) { return i1 > i2; }};int main(){ vec原创 2021-09-26 20:13:06 · 261 阅读 · 0 评论 -
main函数执行前都执行了什么代码
class Test01{public: Test01() { cout << "Test01" << endl; }};class Test02{public: Test02() { cout << "Test02" << endl; }public: static Test01 obj;};Test01 Test02::obj;Test01 tes原创 2021-09-08 16:40:35 · 1110 阅读 · 0 评论 -
lambda,std::function,std::bind
1、lambdalambda表达式形式如下:[捕获列表](参数列表) -> 返回类型 {函数体}捕获列表分为值捕获,引用捕获和隐式捕获(1)值捕获int main(){ int a = 30; auto f = [a] { return a; }; a = 0; auto j = f(); cout << j << endl;//j为30 return 0;}(2)引用捕获int main(){ int a = 30; auto f =原创 2021-09-01 17:00:37 · 211 阅读 · 0 评论 -
const和mutable关键字
在C++中,存在着mutable关键字,之前一直没接触过,最近面试被问到了这个关键字,特此总结一下。mutalbe的意思是“可变”,和C++中的const相反,在C++中,mutable也是为了突破const的限制而设置的。被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中。class A{public: A() { this->number = 0; }private: mutable int number;public: int getNum()原创 2021-09-01 11:30:19 · 2744 阅读 · 0 评论 -
set元素和作为map的key条件
像int,double,string这些类型无论是放在set中或者是作为map的key都没问题,这是因为这些类型重载了<运算符,作为set或者map的key的必要条件是重载<运算符或者传入比较的函数对象。1、重载<运算符class Person{public: int age; int id; Person(int age, int id) :age(age), id(id) {}; bool operator<(const Person& p)const原创 2021-08-26 09:45:13 · 987 阅读 · 0 评论 -
std::vector判断是否存在某个元素
最近工作中需要判断vector中是否存在某个元素,以为有contain这个方法,没想到没有,网上查了相关资料,需要使用到相关算法。1、find vector<string> v; v.push_back("a"); v.push_back("b"); if (std::find(v.begin(), v.end(), "a") != v.end()) { }2.count vector<string> v; v.push_back("a"); v.push_原创 2021-08-10 15:39:08 · 3081 阅读 · 0 评论 -
名字隐藏问题
写出下面程序的输出:class Base{public: virtual void print(int a) { cout << "Base print int " << a << endl; } virtual void print(char a) { cout << "Base print char " << a << endl; } virtual void print(double a) { cout <<原创 2021-07-20 11:59:06 · 157 阅读 · 0 评论 -
类型转换操作符
在C语言中,只有强制类型转换 int i = 1; double j = 1.1; int a = (int)j; double b = (double)i;这种方式简单粗暴,并且不安全,因此,C++提供了四种类型转换操作符static_caststatic_cast可以完全代替C风格的类型转换,实现基本类型转换。在对象指针之间进行转换时,可以将父类指针转换成子类指针,也可以将子类指针转换成父类指针,但是如果两个类是不相关的,则无法完成转换。需要注意的是,如果父类指针指向一个父类对象,此时原创 2021-06-11 10:44:13 · 360 阅读 · 0 评论 -
C++完美转发
完美转发指的是函数模板可以将自己的参数“完美”地转发给内部调用的其它函数。所谓完美,就是能保证被转发参数的左、右值属性不变。引入template<typename T>void function(T t) { otherdef(t);}如上所示,function() 函数模板中调用了 otherdef() 函数。完美转发指的是:如果 function() 函数接收到的参数 t 为左值,那么该函数传递给 otherdef() 的参数 t 也是左值;反之如果 function() 函数原创 2021-05-31 15:54:25 · 617 阅读 · 0 评论 -
容器删除或添加元素后迭代器失效问题
list,set,map等以节点形式存储的容器正确写法1: list<int>li{1,2,3,4}; for (auto it = li.begin(); it != li.end();) { if (*it == 2) { it = li.erase(it); } else { it++; } }正确写法2:for (auto it = li.begin(); it != li.end();) { if (*it == 2) {原创 2021-05-31 12:15:11 · 2762 阅读 · 2 评论 -
枚举中位运算符应用
枚举中使用位运算符可以实现对多个枚举的判断enum Fruit{ eBanana = 1 << 0, eApple = 1 << 1, ePear = 1 << 2, eWatermelon = 1 << 3, ePineapple = 1 << 4 };vector<string> fruitType(Fruit f){ vector<string> v; if (f & eBanana)原创 2021-05-20 13:41:30 · 201 阅读 · 0 评论 -
智能指针实现原理
std智能指针原创 2021-05-20 11:06:10 · 784 阅读 · 1 评论 -
空指针和野指针
空指针在C++中,空指针有两种表示方式:NULL和nullptr。可以看到,在C++中,NULL和0等价,而在C中NULL等价于(void *)0nullptr 是 nullptr_t 类型的右值常量,专用于初始化空类型指针。nullptr_t 是 C++11 新增加的数据类型,可称为“指针空值类型”。也就是说,nullptr 仅是该类型的一个实例对象(已经定义好,可以直接使用),如果需要我们完全定义出多个同 nullptr 完全一样的实例对象。...原创 2021-05-17 09:19:29 · 227 阅读 · 0 评论