自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(416)
  • 收藏
  • 关注

原创 CMake:流程控制(十)

在 CMake 的 CMakeLists.txt 中也可以进行流程控制,也就是说可以像写 shell 脚本那样进行条件判断和循环。的另一个变体,通过这种方式我们可以对更加复杂的数据进行遍历,前两种方式只适用于对某个正整数范围内的遍历。在进行条件判断的时候,如果有多个条件,那么可以写多个。进行循环,关于循环结束对应的条件判断的书写格式和。通过这种方式,遍历的还是一个或多个列表组成一个。的形式(python很常见)判断某个元素是否在列表中。,最后一个条件可以使用。比较两个路径是否相等。

2024-05-03 14:56:57 603

原创 CMake:静态库链接其他动态库或静态库(九)

根目录的CMakeLists.txt编写。对于下面这样一个项目。

2024-05-03 13:46:32 365

原创 CMake:嵌套的CMake与多级项目管理(八)

如果项目很大或者项目中有很多的源码目录,在通过CMake管理项目的时候如果只使用一个。,那么这个文件会相对比较复杂,有一种化繁为简的方式就是给每个源代码目录都添加一个。Linux中的目录是一个梳妆结构,所以嵌套的CMake也是一个梳妆结构,最顶层的。文件(头文件不需要),这样每个文件都不会太复杂,而且更灵活,更容易维护。接下来可以依次分析一下各个文件中需要添加的内容。calc目录下的源代码打包生成一个。sort目录下的源代码打包生成一个。文件,并且存放到指定的目录下。文件,并且存放到指定的目录下。

2024-05-02 23:55:59 1257

原创 CMake:自定义与预定义宏(七)

5int main()std::cout << "这是一行调试信息";#elsestd::cout << ", MAXN没有被定义";在程序中对DEBUG如果该宏被定义了,那么会进行调试输出如果没有定义这个宏,这段代码就相当于被注释掉了,因此最终无法看到日志输出为了让测试更灵活,我们可以不再代码中定义这个宏,而是在测试的时候去把它定义出来,其中就可以通过g++/gcc命令去指定-D:表示植入宏。

2024-05-02 20:31:47 48

原创 CMake:set与list的字符串操作(六)

关于上面的命令其实就是将从第二个参数开始往后所有的字符串进行拼接,最后将结果存储到第一个参数中,如果第一个参数中有数据就会对元数据进行覆盖。搜索某个目录就得到该目录下所有的源文件,但是其中有些源文件并不是我们所需要的,比如:制作库需要移除main.cpp文件。命令对这个目录下的源文件进行搜索,最后还需要做一个字符串拼接的操作,关于字符串拼接可以使用。要强大,字符串拼接只是它的其中一个功能,所以需在在它第一个参数的位置指定出外面要做的操作,:新创建的变量,用户存储索引元素的返回结果,也是一个列表。

2024-05-02 19:45:29 762

原创 CMake:编译日志信息的使用(五)

CMake警告和错误消息的文本显示使用的是一种简单的标记语言。文本没有锁紧超过长度的行会回卷,段落之间以新行作为分隔符。上显示其他所有消息。CMake的GUI会在它的log区域显示所有消息。在CMake中可以用用户显示一条信息,该命令的名字为。CMake的命令行工具会在。

2024-05-02 16:50:34 120

原创 CMake:静态库和动态库的制作与使用(四)

传递性:动态库的链接具有传递性,如果动态库A链接了动态库B、C,动态库D链接了动态库A,此时动态库D相当于也链接了动态库B、C,并可以使用动态库B、C中定义的方法。有些时候我们编写的源代码并不需要将他们编译生成可执行程序,而是生成一些静态库或者动态库提供给第三方使用,而在CMake中生成这两类库文件的方法。在程序编写过程中,除了在项目中引入静态库,好多时候也会使用一些标准的或者第三方提供的动态库,例如:基础IO流库、多线程库…动态库的链接和静态库的链接是完全不同的。对于使用静态库和动态库是有区别的。

2024-05-02 16:49:09 912

原创 CMake:搜索文件和指定头文件目录(三)

如果一个项目中的源文件很多,在编写CMakeLists.txt文件的时候不可能将项目目录的各个文件一一罗列出来,这样麻烦也不现实。所以在CMake中为我们提供了搜索文件的命令,可以使用。在CMake中使用aux_source_directory命令可以查找某个文件夹下的所有源文件,命令格式如下。当头文件和源代码不在一个文件夹下,需要在源代码中引入头文件具体的位置或者指定头文件的路径。刚才的命令是直接搜索某个目录下的所有源代码文件。而file命令可以搜索目录下指定类型的文件。

2024-04-29 16:22:58 226

原创 CMake:set函数定制变量的使用(二)

在上面的例子用,假设这五个源文件反复被使用,每次都直接把它们的名字写出来是一件很麻烦的事情,此时可以通过定义一个变了,将文件名字的字符换存储起来,在cmake里定义变量需要使用set。# SET指令的语法:[]中的为可选参数,如果不需要刻意不写# VARIABLE_NAME:变量名称# VALUE:变量值# []中的为可选指令例如对于多文件编译,可以将源文件定义到一个变量里到处引用# set定义的变量值之间以' '或者';'分隔开mul.cpp;add.cpp;sub.cpp;dived.cpp)

2024-04-29 16:19:03 235

原创 CMake:相关概念与使用入门(一)

Cmake是一个项目构建工具,并且是跨平台的。关于项目构建我们所熟知的有Makefile,然后通过make命令进行项目的构建,并且大多数是IDE都继承了make,比如:VS的nmake,Linux下的GNU make、Qt的qmake等。如果自己手动写makefile,会发现makefile通常依赖当前的编译平台,并且makefile的工作量比较大,解决依赖关系也容易出错。

2024-04-25 21:46:17 319

原创 C++高级特性:异常概念与处理机制(十四)

异常被抛出后,从进入try块起到异常抛出前(throw),这期间在栈上创建的所有对象都会被自动析构。这种情况就可以考虑使用多态的特性了,定义基类异常,所有可能的异常都继承基类异常,而捕获时只需要捕获基类异常即可。异常:是指在程序运行的过程中发生的一些异常事件(如:除数为0,数组下标越界,栈溢出,访问非法内存等)推荐使用抛出引用类型的异常处理,不会进行拷贝和手动分配堆区空间的问题,不会造成内存泄漏和性能负担。runtime_error子类。logic_error子类。

2024-04-24 10:28:16 797

原创 C++高级特性:虚函数与多态的实现原理(十三)

如果一个类存在virtual关键字函数或者继承的基类中存在virtual关键字的函数,那么该类的就会存在vptr和一个vtable。空类的大小为1字节,而存在虚函数(虚析构函数或其他虚函数)那么就会为该类生成一个vptr虚函数表指针和一个vtable虚函数表。其次调用本类的构造函数进行构造,如果本类存在vtable那么将本类的vtable地址赋值给vptr。时,a指针通过构造函数进行初始化,此时a内部的vptr指针会指向A的虚函数表vtable。如果没有构造函数,编译器会生成默认的空构造函数。

2024-04-22 16:08:42 595

原创 C++设计模式:中介者模式(十五)

定义:用一个中介对象来封装(封装变化)一系列的对象交互。中介者使各个对象不需要显示的相互引用(编译时依赖 -> 运行时依赖),从而使其耦合松散(管理变化),而且可以独立地运改变它们之间的交互。在软件构建过程中,经常会出现多个对象相互关联交互的情况,对象之间常常会维持一种付啊的引用关系,如果遇到一些需求的更改,这种直接的引用关系将面临不断的变化。在这种情况下,我们可以使用一个“中介对象”来管理对象之间的关联关系,避免相互交互的对象之间的紧耦合引用关系,从而更好地抵御变化。

2024-04-22 13:26:43 425

原创 C++高级特性:malloc、free和new、delete的区别(十二)

malloc、free都是用于动态分配内存空间的操作,malloc是C语言中的库函数,new是C++中的操作符。delete需要对象类型的指针,它通过调用析构函数进行释放当对指针类型进行擦除或者强制转换后会导致出现异常。free传入void *类型的指针即可,但是free有个很重要的问题,它怎么知道需要释放多大的空间?new是在free store上分配内存的,free store的意思就是可以自由分配。new返回的是对象类型的指针,malloc返回的是void *之后进行类型转换。

2024-04-22 10:40:26 535

原创 C++高级特性:C/C++内存结构模型(十一)

代码段可制度数据段通常在程序加载时有操作系统加载到内存,一旦加载就不能被修改在函数调用时,函数的机器码也存储在代码段中,每个函数有其独特的代码段地址字符串常量等只读数据段中的数据是不可修改的,任何企图修改这些数据的尝试都会导致运行时错误作为一个专业的C++使用者来说,清楚的知道自己的代码变量存储的区域会有非常大的好处,补单能够写出高性能代码,而且有助于减少一些深层次的BUG。使用C++内存的一些注意事项内存泄漏:确保在动态分配内存后找个合适的时机释放掉,避免出现内存泄漏。

2024-04-21 17:48:24 1402 2

原创 C++设计模式:适配器模式(十四)

定义:将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的哪些类可以一起工作。在软件系统中,由于应用环境的变化,常常需要将“一些现存的对象”放在新的环境中应用,但新环境要求的接口是这些现存对象所不满足的。如何应对这种“迁移的变化”?如何既能利用现有对象的良好视线同时又能满足心得应用环境所要求的接口?

2024-04-21 13:41:30 441

原创 C++高级特性:nullptr和NULL的区别(十)

可以看到nullptr被定义为nullptr_t类型同时nullptr_t的类型长度与void *长度相同>=201103L#endif而nullptr_t也可以定义一个其他指针的空指针对象并且与nullptr有相同的能力,而且被创建的对象是一个左值//报错,右值没有地址。

2024-04-19 11:07:50 435

原创 C++高级特性:四种类型转换(九)

C++标准规定,试图修改一个被声明为。

2024-04-18 21:14:58 799

原创 C++高级特性:可变长模板参数和折叠表达式(八)

&表示万能引用,需要注意的是如果不使用万能引用,传入参数的类型需要注意是左值还是右值,要与模板的参数类型匹配。可变长参数是C++类模板编程中非常重要的一个东西,也是C++11引入的新特性,通过使用…来表示参数长度不固定。可以通过sizeof…(args)获取传入参数的个数数量。C++11之后写这种模板函数的递归需要写一个空参函数和。参数,而在C++17之后可以折叠表达式展开。

2024-04-18 21:13:23 140

原创 C++设计模式:代理模式(十三)

增加一层”是软件系统重对许多复杂问题的一种常见解决方法。在面向对象系统中,直接使用某些对象会带来很多问题,作为间接层的proxy对象便是解决这一问题的常用手段。具体proxy设计模式的实现方法、实现粒度都相差很大,有些可能对单个对象做细粒度的控制,如copy-on-write技术,有些可能对组件模块提供抽象代理层,在架构层次对对象做proxy(例如aop)Proxy并不一定要求保持接口完整的一致性,只要能够实现间接控制,有时候损失一些透明性也是可以接受的。

2024-04-13 22:25:41 1032

原创 C++高级特性:万能引用、引用折叠与完美转发(七)

由于出现了万能引用,现在传入参数就会变得很复杂,一会传入左值一会传入右值,通过模版参数接手的时候,实际上编译器呢会进行引用折叠的一个操作。那现在的结果就跟我们的需求背道而驰了啊,希望func(std::move(s))调用右值引用的func_push。万能引用:无论传入什么值还是引用都能够接收,并且确定其一个准确的类型,通过引用折叠的方式。一个左值引用的func_push、一个右值引用的func_push函数,二者是重载的关系。完美转发:我按照小明给我的方式(拷贝or移动)使用,这就叫完美转发!

2024-04-13 15:30:41 837

原创 C++高级特性:柯里化过程与std::bind(六)

其实上面的链式编程或者函数式编程就是一个柯里化的过程,其实这种操作在lambda表达式也有体现的,lambda表达式中继续lambda表达式。通过分析可以看到add(1)应该返回一个类似函数的东西func,然后这个东西还可以继续func(2)…现在需要完成这样一个需求:有一个函数每次调用返回的结果不一样。可以给一个全局的变量(静态变量),每次调用对这个全局变量进行值的修改然后返回,这样每次返回都不一样。如果需要用类来完成,那么可以使用operator()仿函数来做,仿函数其实是一个特殊的函数。

2024-04-12 20:55:04 464

原创 C++设计模式:门面模式(十二)

接口隔离”模式:在组建构建过程中,某些接口之间直接的依赖常常会带来很多问题、甚至根本无法实现。采用添加一层间接(稳定)接口,来隔离本来相互紧密关联的接口是一种常见的解决方案。门面设计模式定义:为子系统中的一组接口提供一个一致(稳定)的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用(复用)。上述A方案的问题在于组件的客户和组件中各种复杂的子系统有了过多的耦合,随着外部客户程序和各子系统的烟花,这种过多的耦合面临很多变化的挑战。如何简化外部客户程序和系统间的交互接口?

2024-04-12 16:16:20 699

原创 C++高级特性:右值引用与转移语义(五)

所有权的转移取决于实现。移动语义并没有太多神奇的事情去做,std::move只是用来匹配到移动构造(移动赋值)所有权与移动语义密不可分,可以说移动语义的诞生就是为了区分这个到底是转移所有权还是进行拷贝复制。

2024-04-12 14:15:37 345

原创 C++高级特性:重新理解左值、右值、左值引用与右值引用详解(四)

另外还有引用初始化的问题,引用只能在定义的时候初始化(定义的时候必须指定一个类型)。定义完毕无法初始化和修改指向,虽然无法修改指向但是可以修改值。b = y:实际上是将y的右值给了b当右值,不是把y的左值给了b当右值。int&b = x;b = y;/* 输出*/左值引用不是引用不了一个临时变量值吗,那右值引用来引用临时变量(东厂管不了的西厂管)右值引用却无法引用一个存在地址的左值(有实际地址)// 报错int t = 10;int& a = t;// 报错。

2024-04-11 23:48:00 1190

原创 C++设计模式:享元模式(十一)

概述:享元模式和单例模式一样,都是为了解决程序的性能问题。面向对象很好地解决了"抽象"的问题,但是必不可免得要付出一定的代价。对于通常情况来讲,面向对象的成本大豆可以忽略不计。但是某些情况,面向对象所带来的成本必须谨慎处理。定义:运用共享技术有效地支持大量细粒度的对象。在软件系统中采用纯粹对象方案的问题在于大量细粒度的对象会很快充斥在系统中,而带来很高的运行时代价——主要指内存需求方面的代价。如何避免大量细粒度对象问题的同时,让外部客户程序仍然能够透明地使用面向对象的方式来进行操作?

2024-04-11 18:41:32 583

原创 C++高级特性:共享指针shared_ptr和弱指针weak_ptr(三)

一个函数返回一个unique_ptr的智能指针有一个很强的兼容性,可以用unique_ptr接受也可以用shared_ptr接受。很明显这里会发现university和teacher相互依赖,导致shared_ptr的计数引用无法降为0形成了死锁。unique_ptr可以转化为shared_ptr,shared_ptr无法转化为unique_ptr。解决方案:只需要将其中一个的shared_ptr弱化成weak_ptr指针即可。在释放对象时二者都不肯先一步析构,最后无法析构导致内存泄漏。

2024-04-11 15:12:53 191

原创 C++高级特性:独享智能指针unique_ptr(二)

C++11中通过引入智能指针的概念,使得C++程序员不需要手动释放内存。先准备一个Cat.h和一个Cat.cpp,如下。

2024-04-11 15:11:25 1069

原创 C++高级特性:Lambda表达式(一)

f1和f2是同一个函数都是用于求a + b的和其中函数f1和f2的类型可以具体指定通过std::function模板类来指定,也可以通过auto自动类型推导对于lambda表达式,不光可以函数类型自动推导,函数的传入参数、返回类型都可以自动推导…f3的lambda表达式相当于auto f3(auto a, auto b)这样一个函数f3(auto a, auto b)很好理解,可以当做一个函数模板来看,结果人家在函数模板的基础在返回类型继续auto…(C++14新特性)

2024-04-10 22:35:16 599

原创 C++设计模式:单例模式(十)

由于程序运行CPU会进行指令的重排序,如果执行的指令是132顺序,A线程执行完13之后并没有完成对象的初始化、而这时候转到B线程;不能重复创建、也必须保证这个对象在多线程使用过程中不会因为创建而产生数据安全问题,即多线程抢占的创建这一个对象。可以看到实例化不止一个单例对象,这一现象违反了单例的思想,因此需要在多线程抢占创建时进行互斥(mutex)对外暴露一个public方法获取该对象,如果在获取时发现该对象为空,那么进行实例化,否则直接返回。因此可以看到实例化只有一次,多次获取到的对象的地址属于同一个。

2024-04-10 18:55:40 894

原创 C++设计模式:构建器模式(九)

定义:将一个复杂对象的构建与其表示相分离,使得同样的构建过程(稳定)可以创建不同的表示(变化)在软件系统中,有时候面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构建而成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定如何应对这种变化?如何提供一种“封装机制”来隔离出“复杂对象的各个部分”的变化,从而保持系统中的“稳定构建算法”不随着需求改变而改变?

2024-04-10 17:02:14 594

原创 C++:Stmt预处理SQL与大文件存取(五)

这里主要通过ftsream来计算文件的大小,也可以通过其他手段,例如stat.h、lseek函数(Linux环境)MySQL中存取文件可以用blob来表示,表示使用二进制的方式存储。

2024-04-09 19:51:19 351

原创 C++设计模式:原型模式(八)

定义:使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新的对象。在软件系统中,经常面临着“某些结构复杂的对象”的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是它们却拥有比较稳定一直的接口如何应对这种变化?如何向“客户程序(使用这些对象的程序)”隔离处“这些易变对象”,从而使得“依赖这些易变对象的客户程序”不随着需求改变而改变?个人理解:当一个类对象创建复杂、或者需要当前状态且当前状态这个对象又不允许被破坏的情况下,为了重复利用就可以考虑使用原型模式来clone一个对象。

2024-04-09 14:18:24 704

原创 C++设计模式:抽象工厂模式(七)

抽象工厂定义:提供一个接口,让该接口负责创建一系列“相关或者相互依赖的对象”,无需指定它们具体的类动机:在软件系统中,经常面临着“一系列相互依赖的对象”的创建工作;同时,由于需求的变化,往往存在更多系列对象的创建工作。如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种“封装机制来避免客户程序和这种“多系列具体对象创建工作”的紧耦合?个人理解:在工厂方法的基础上套上了一层封装接口,封装的意义就是为了在工厂方法的基础上返回一套或者同类的相互依赖的一系列对象!

2024-04-09 10:45:22 567

原创 C++设计模式:工厂方法模式(六)

对象创建模式:通过对象创建模式绕开new,来避免对象(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定。它是接口抽象之后的第一步工作。PrototypeBuilder工厂模式定义:定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使得一个类的实例化延迟(目的:解耦,手段:虚函数)到子类。动机在软件系统中,经常面临着创建对象的工作;由于需求的变化,需要创建的对象的具体类型经常变化。如何应对这种变化?

2024-04-08 16:03:13 978

原创 C++:MySQL的事务概念与使用(四)

脏读是致命的操作,因为拿到的数据是无效数据;而不可重复度与幻读是一种现象,只是先后读取不一致的问题,但是数据是有效的(其他事物成功提交)!

2024-04-07 23:40:05 715 1

原创 C++:MySQL数据库的增删改(三)

C/C++操纵数据库的方式便捷性太差,虽然JDBC的也很烂,但是JDBC有开源的ORM框架(mybatis、jooq、hiberate、springdata…),不敢想象如果全裸使用C/C++写一些业务会有多痛苦,捂脸!

2024-04-07 19:23:50 413

原创 C++设计模式:桥模式(五)

桥模式定义:将抽象部分(业务功能)与实现部分(平台实现)分离,使他们可以独立地变化引入动机由于某些类型的固有的实现逻辑,使得它们具有两个变化的维度,乃至多个维度的变化如何应对这种“多维度的变化”?如何利用面向对象技术来使用类型可以轻松地沿着两个乃至多个方向变化,二部引入额外的复杂度?Bridge模式使用“对象间的组合关系”解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。所谓抽象和实现沿着各自维度的变化,即“子类化”它们。

2024-04-07 14:51:53 693

原创 C++:执行SQL和获取查询结果(二)

遍历和清理结果集api:mysql_fetch_row、mysql_fetch_lengths、mysql_free_result。获取结果集api:mysql_use_result、mysql_store_result。执行sql语句的api:mysql_real_query和mysql_query。

2024-04-06 23:54:00 558

原创 C++:连接MySQL数据库(一)

mysql_real_connect函数:用于与MySQL数据库建立连接。mysql_options函数:用于设置一些连接超时、断开重连等。

2024-04-06 18:13:10 651

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除