
c++
文章平均质量分 67
GoodLinGL
这个作者很懒,什么都没留下…
展开
-
C++11多线程:thread头文件
std:thread1. std::thread(class)线程构造(constructor)joinable线程状态operator=joindetachget_idnative_handleswaphardware_concurrency2. std::this_thread(namespace)get_idsleep_forsleep_untilyield#include头文件中主要包含两个内容:std:thread类和std:this_thread命名空间。1. std::thread(cla转载 2021-04-26 17:01:55 · 2059 阅读 · 0 评论 -
C++多线程中的join, detach, joinable
thread是C++11中提供多线程编程的模块,使用的时候需要包含<thread>头文件。首先我们先来看一下简单的hello world的多线程的代码在这里插入图片描述这个创建的方式就是以函数作为一个入口,创建了一个子线程,那么创建的语句就是第11行代码所示,所传入的参数就是入口的函数名。在创建了这个子线程之后,这个子线程就开始运行了,同时主线程也不停的往下运行,当碰到t.join()这句代码的时候,就表示主线程需要等待子线程运行结束回收掉子线程的资源后,再往下运行,否则就会产生一种情况转载 2021-04-26 16:02:18 · 349 阅读 · 0 评论 -
C++11线程中的几种锁
线程之间的锁有:互斥锁、条件锁、自旋锁、读写锁、递归锁。一般而言,锁的功能与性能成反比。不过我们一般不使用递归锁(C++标准库提供了std::recursive_mutex),所以这里就不推荐了。互斥锁(Mutex)...转载 2021-04-26 13:29:59 · 8265 阅读 · 0 评论 -
C++ 加锁的原则
规则1 多线程、进程并行访问共享资源时,一定要加锁保护说明:共享资源包括全局变量,静态变量,共享内存,文件等。 建议封装像智能指针一样的对象对锁进行管理,比如我们就封装了一个auto_lock,在构造时申请 锁,析构中释放锁,保证不会忘记“解锁”。如果锁的作用范围有限,则可以这样: do { auto_lock lock(&lock); //… }while(0);规则2 锁的职责单一说明:每个锁只锁一个唯一共享资源;这样,才能保证锁应用的单一,也能更好的确保加锁的范围尽 量小。转载 2021-04-23 08:42:06 · 2691 阅读 · 0 评论 -
c++内存泄漏和内存碎片
内存泄漏一般我们常说的内存泄漏是指堆内存的泄漏。堆内存是指程序从堆中分配的,大小任意的(内存块的大小可以在程序运行期决定),使用完后必须显示释放的内存。应用程序一般使用malloc,realloc,new等函数从堆中分配到一块内存,使用完后,程序必须负责相应的调用free或delete释放该 内存块,否则,这块内存就不能被再次使用,我们就说这块内存泄漏了。对于C和C++这种没有Garbage Collection 的语言来讲,我们主要关注两种类型的内存泄漏:堆内存泄漏(Heap leak):对内存指的转载 2021-04-22 19:24:02 · 839 阅读 · 0 评论 -
GDB(调试工具)
什么是GDBGDB是GNU开源组织发布的一个强大的Linux下的程序调试工具。一般来说,GDB主要帮助你完成下面四个方面的功能:启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)当程序被停住时,可以检查此时你的程序中所发生的事。动态的改变你程序的执行环境。GDB调试的对象GDB主要来调试C/C++语言写的程序,当然也就可以调试其他语言程序。GDB调试一定要是可执行文件而不是.c文件。要用gcc转载 2021-04-09 15:20:04 · 2717 阅读 · 0 评论 -
C++的特性
C是面向过程的语言,是一个结构化的语言,考虑如何通过一个过程对输入进行处理得到输出;C++是面向对象的语言,主要特征是“封装、继承和多态”。封装隐藏了实现细节,使得代码模块化;派生类可以继承父类的数据和方法,扩展了已经存在的模块,实现了代码重用;多态则是“一个接口,多种实现”,通过派生类重写父类的虚函数,实现了接口的重用。C和C++动态管理内存的方法不一样,C是使用malloc/free,而C++除此之外还有new/delete关键字。C++支持函数重载,C不支持函数重载C++中有引用..转载 2021-04-08 10:52:49 · 2132 阅读 · 0 评论 -
内存对齐
内存对齐内存对齐”应该是编译器的“管辖范围”。编译器为程序中的每个“数据单元”安排在适当的位置上。对于内存对齐问题,主要存在于struct和union等复合结构在内存中的分布情况,许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们要求这些数据的首地址的值是某个数M(通常是4或8);对于内存对齐,主要是为了提高程序的性能,数据结构,特别是栈,应尽可能在自然边界上对齐,经过对齐后,cpu的内存访问速度大大提升。Windows中默认对齐数为8,Linux中默认对齐数为4;内存对齐的主要作原创 2021-03-29 21:31:10 · 1585 阅读 · 0 评论 -
C++调用Python的API
C++ 调用Python流程首先需要包含头文件 Python.h初始化Python环境 Py_Initialize()添加模块路径(或者说脚本路径)PyRun_SimpleString()导入模块PyImport_ImportModule()导入函数PyObject_GetAttrString()使用函数PyObject_CallObject()获取结果PyArg_Parse()结束释放Py_DECREF()、Py_Finalize()初始化和关闭Python解释器所有的Python转载 2021-03-23 10:03:57 · 665 阅读 · 0 评论 -
设计模式
设计模式有 6 大设计原则单一职责原则:基于一个类而言,应该只有一个引起它变化的原因。开放封闭原则:软件实体可以扩展,但不能修改。即面对需求,对程序的改动可以通过增加代码来完成,但不能通过修改现有代码。里氏代换原则:一个软件实体如果使用的是一个基类,那么一定适用于其派生类。即在软件中,把基类替换成派生类,程序的行为没有变化。依赖倒转原则:抽象不应该依赖细节,细节应该依赖抽象。即针对接口编程,而不是针对实现编程。迪米特原则:如果两个类不直接通信,那么这两个类就不应当发生直接关系。如果一个类要调用另转载 2021-03-10 23:08:28 · 121 阅读 · 0 评论 -
模板的全特化与偏特化
模板分为类模板与函数模板,特化分为全特化与偏特化。全特化就是限定死模板实现的具体类型,偏特化就是如果这个模板有多个类型,那么只限定其中的一部分。类模板可以全特化,也可以偏特化:template<typename T1, typename T2>class Test{public: Test(T1 i,T2 j):a(i),b(j){cout<<"模板类"<<endl;}private: T1 a; T2 b;}; template<>转载 2021-03-10 20:50:02 · 743 阅读 · 0 评论 -
常量指针和指针常量
一、常量指针定义: 常量指针本质上是个指针,只不过这个指针指向的对象是常量。声明: const 的位置在指针声明运算符 * 的左侧。* 左侧表示指针指向的对象,该对象为常量,那么该指针为常量指针。const int * p;int const * p;注意: 常量指针指向的对象不能通过这个指针来修改,但是因为常量指针本身是一个变量,因此,可以被重新赋值。#include <iostream>using namespace std;int main(){ const转载 2021-03-10 17:01:46 · 2766 阅读 · 3 评论 -
C++右值引用
一、左值和右值左值:指表达式结束后依然存在的持久对象。右值:表达式结束就不再存在的临时对象。简单来说就是,左值相当于地址值,右值相当于数据值。int i=42;int &r=i; //正确,r引用iint &&rr=i //错误,不能将一个右值引用绑定到一个左值上int &r2=i*42; //错误,i*42是一个右值const int &r3=i*42; //正确,我们可以将一个const的引用绑定到一个右值上int &&原创 2021-03-10 16:22:36 · 112 阅读 · 0 评论 -
如何让类不能被继承
方法一:借助 final 关键字,用该关键字修饰的类不能被继承。#include <iostream>using namespace std;class Base final{};class Derive: public Base{ // error: cannot derive from 'final' base 'Base' in derived type 'Derive'};int main(){ Derive ex; return 0;}转载 2021-03-10 15:50:45 · 1087 阅读 · 0 评论 -
深拷贝和浅拷贝
如果一个类拥有资源,该类的对象进行复制时,如果资源重新分配,就是深拷贝,否则就是浅拷贝。深拷贝: 该对象和原对象占用不同的内存空间,既拷贝存储在栈空间中的内容,又拷贝存储在堆空间中的内容。浅拷贝: 该对象和原对象占用同一块内存空间,仅拷贝类中位于栈空间中的内容。当类的成员变量中有指针变量时,最好使用深拷贝。因为当两个对象指向同一块内存空间,如果使用浅拷贝,当其中一个对象的删除后,该块内存空间就会被释放,另外一个对象指向的就是垃圾内存。#include <iostream>usin原创 2021-03-10 15:36:52 · 189 阅读 · 0 评论 -
类的实例化
类的实例化实例化一个对象的过程如何减少构造函数开销实例化一个对象的过程分配空间: 全局对象、静态对象、分配在栈区域内的对象,在编译阶段进行内存分配;存储在堆空间的对象,是在运行阶段进行内存分配。初始化: 首先明确一点:初始化不同于赋值。初始化发生在赋值之前,初始化随对象的创建而进行,而赋值是在对象创建好后,为其赋上相应的值。初始化列表先于构造函数体内的代码执行,初始化列表执行的是数据成员的初始化过程。赋值: 对象初始化完成后,可以对其进行赋值。对于一个类的对象,其成员变量的赋值过程发生在转载 2021-03-10 15:11:28 · 3758 阅读 · 0 评论 -
虚基类(多重继承)
多重继承容易出现的问题:命名冲突和数据冗余问题。#include <iostream>using namespace std;// 间接基类class Base1{public: int var1;};// 直接基类class Base2 : public Base1{public: int var2;};// 直接基类class Base3 : public Base1{public: int var3;};// 派生类cl原创 2021-03-10 11:06:05 · 1088 阅读 · 1 评论 -
虚函数
定义虚函数:被 virtual 关键字修饰的成员函数。纯虚函数: 在类中声明虚函数时加上 =0;抽象类:含有纯虚函数的类(只要含有纯虚函数这个类就是抽象类),类中只有接口,没有具体的实现方法。继承纯虚函数的派生类,如果没有完全实现基类纯虚函数,依然是抽象类,不能实例化对象。说明:抽象类对象不能作为函数的参数,不能创建对象,不能作为函数返回类型;可以声明抽象类指针,可以声明抽象类的引用;子类必须继承父类的纯虚函数,并全部实现后,才能创建子类的对象。...原创 2021-03-10 10:00:08 · 1314 阅读 · 0 评论 -
strcpy 函数有什么缺陷
函数里的局部变量一般都是按序排放的,并且因为是分配在堆栈之中,它们的地址是向下“增长”,即向低地址方向增长。比如下面的程序: int flag=0x12345678; printf("%x\n",flag); char s[6]; printf("address of flag: %x\n",&flag); printf("address of array s: %x\n",s); strcpy(s,"my aaaa"); printf("%s\n转载 2021-03-09 22:09:13 · 864 阅读 · 0 评论 -
memcpy 函数
原理memcpy函数是C/C++语言中的一个用于内存复制的函数,声明在 string.h 中(C++是 cstring)。其原型是:void *memcpy(void *destin, void *source, unsigned n);作用是:以source指向的地址为起点,将连续的n个字节数据,复制到以destin指向的地址为起点的内存中。函数有三个参数,第一个是目标地址,第二个是源地址,第三个是数据长度。使用memcpy函数时,需要注意:数据长度(第三个参数)的单位是字节(1byte转载 2021-03-09 21:43:22 · 117538 阅读 · 11 评论 -
struct, union, class
一、C 和 C++ struct 的区别在 C 语言中 struct 是用户自定义数据类型;在 C++ 中 struct 是抽象数据类型,支持成员函数的定义。C 语言中 struct 没有访问权限的设置,是一些变量的集合体,不能定义成员函数;C++ 中 struct 可以和类一样,有访问权限,并可以定义成员函数。C 语言中 struct 定义的自定义数据类型,在定义该类型的变量时,需要加上 struct 关键字,例如:struct A var;,定义 A 类型的变量;而 C++ 中,不用加该关键字,原创 2021-03-09 21:08:28 · 238 阅读 · 0 评论 -
new和delete,malloc和free
一、申请内存new :内存分配成功,返回该对象类型的指针;分配失败,抛出 bac_alloc 异常。malloc :成功申请到内存,返回指向该内存的指针;分配失败,返回 NULL 指针。在使用的时候 new、delete 搭配使用,malloc、free 搭配使用。二、释放内存delete执行过程:首先执行该对象所属类的析构函数;进而通过调用 operator delete 的标准库函数来释放所占的内存空间。delete 和 delete [] 的区别:delete 用来释放单个原创 2021-03-09 20:16:56 · 428 阅读 · 0 评论 -
inline 内联函数
作用对于一些功能简单、规模较小又使用频繁的函数,可以设计为内联函数。内联函数不是在调用时发生控制转移,而是在编译时将函数体嵌入在每一个调用处。这样可以大大减少由函数调用带来的开销,从而提高程序的运行效率。inline 是一个关键字,可以用于定义内联函数。使用类内定义成员函数默认是内联函数在类内定义成员函数,可以不用在函数头部加 inline 关键字,因为编译器会自动将类内定义的函数(构造函数、析构函数、普通成员函数等)声明为内联函数,代码如下:class A{public: int原创 2021-03-09 17:31:02 · 209 阅读 · 0 评论 -
define 和 typedef 的区别
原理:#define 作为预处理指令,在编译预处理时进行替换操作,不作正确性检查,只有在编译已被展开的源程序时才会发现可能的错误并报错。typedef 是关键字,在编译时处理,有类型检查功能,用来给一个已经存在的类型一个别名,但不能在一个函数定义里面使用 typedef 。功能:typedef 用来定义类型的别名,方便使用。#define 不仅可以为类型取别名,还可以定义常量、变量、编译开关等。作用域:#define 没有作用域的限制,只要是之前预定义过的宏,在以后的程序中都可以使用,而 t..翻译 2021-03-09 17:09:13 · 241 阅读 · 0 评论 -
const详解
作用const 修饰成员变量,定义成 const 常量,相较于宏常量(详见下文说明1),可进行类型检查,节省内存空间,提高了效率。const 修饰函数参数,使得传递过来的函数参数的值不能改变。const 修饰成员函数,使得成员函数不能修改任何类型的成员变量,mutable (详见下文说明2)修饰的变量除外,也不能调用非 const 成员函数,因为非 const 成员函数可能会修改成员变量。说明1:宏常量:用一个标识符来表示的常量;宏定义(不能以;结尾):#define 标识符 字符串原创 2021-03-09 16:45:53 · 927 阅读 · 0 评论 -
lambda 表达式(匿名函数)
lambda 表达式(匿名函数)的定义:[capture list] (parameter list) -> reurn type{ function body}capture list:捕获列表,指 lambda 表达式所在函数中定义的局部变量的列表,通常为空,但如果函数体中用到了 lambda 表达式所在函数的局部变量,必须捕获该变量,即将此变量写在捕获列表中。捕获方式分为:引用捕获方式 [&]、值捕获方式 [=]。return type、parameter list、原创 2021-03-09 14:47:11 · 311 阅读 · 0 评论 -
c++ 多态的定义和实现
定义多态就是不同继承类的对象,对同一消息做出的不同响应,基类的指针指向或绑定到派生类的对象,使得基类指针呈现不同的表现形式。构成多态的条件:在基类的函数前加上 virtual 关键字,在派生类中重写该函数;调用函数的对象必须是指针或引用。运行时将会根据对象的实际类型来调用相应的函数。如果对象类型是派生类,就调用派生类的函数;如果对象类型是基类,就调用基类的函数。实现多态是通过虚函数实现的,虚函数的首地址存在虚函数表中,虚函数表的地址存在含有虚函数的类的实例对象的内存空间中。实现过程:原创 2021-03-09 11:17:11 · 263 阅读 · 0 评论 -
对象创建限制在堆或栈
C++ 中的类的对象的建立分为两种:静态建立、动态建立静态建立:由编译器为对象在栈空间上分配内存,直接调用类的构造函数创建对象。例如:A a;动态建立:使用 new 关键字在堆空间上创建对象,底层首先调用 operator new() 函数,在堆空间上寻找合适的内存并分配;然后,调用类的构造函数创建对象。例如:A *p = new A();限制对象只能建立在堆上方法一:将析构函数设置为私有。原因:静态对象建立在栈上,是由编译器分配和释放内存空间,编译器为对象分配内存空间时,会对类的非静态函数进翻译 2021-03-08 19:33:04 · 343 阅读 · 0 评论 -
c++内存管理
C++ 内存分区栈:存放函数的局部变量、函数参数、返回地址等,由编译器自动分配和释放。堆:动态申请的内存空间,就是由 malloc 分配的内存块,由程序员控制它的分配和释放,如果程序执行结束还没有释放,操作系统会自动回收。全局区/静态存储区(.bss 段和 .data 段):存放全局变量和静态变量,程序运行结束操作系统自动释放,在 C 语言中,未初始化的放在 .bss 段中,初始化的放在 .data 段中,C++ 中不再区分了。常量存储区(.data 段):存放的是常量,不允许修改,程序运行结束自动转载 2021-03-08 17:24:41 · 172 阅读 · 0 评论 -
C++中复制构造函数的形参能否进行值传递
C++中复制构造函数的形参不能进行值传递,要想知道原因,需要清楚复制构造函数在什么情况下才会调用。调用复制构造函数的三种情况当用类一个对象去初始化另一个对象时。如果函数形参是类对象。如果函数返回值是类对象,函数执行完成返回调用时。即如果是引用的话就不需要调用拷贝构造函数。如果C++中复制构造函数的形参进行的是值传递,这个传递的时候又要调用拷贝构造函数。如此循环,无法完成拷贝,栈也会满。...原创 2021-03-08 16:11:46 · 858 阅读 · 0 评论 -
覆盖,重载和隐藏
定义重载:重载是在一个类中多态性的一种表现,是指在一个类中定义了多个同名的方法,他们或有不同的参数个数,或有不同的参数类型,或参数顺序不同。与访问修饰符,返回值类型及抛出的异常类型无关。对于继承来说,如果父类方法的访问修饰符为private,那么就不能在子类对其重载;如果子类也定义了一个同名的函数,这只是一个新的方法,不会达到重载的效果。覆盖:是指子类函数覆盖父类函数。覆盖一个方法并对其进行重写,以达到不同的作用。子类中的覆盖方法必须要和父类中被覆盖的方法有着相同的函数名、参数、返回值及抛出的异常。原创 2021-03-08 09:43:53 · 893 阅读 · 0 评论 -
函数指针和指针函数
函数指针和指针函数函数指针指针函数函数指针定义:其本质是一个指针变量,就是指向函数的指针。int (*fun)(int x,int y);调用函数指针的方式也有两种:x = (*fun)();x = fun();指针函数定义:是一个返回指针的函数,其本质是一个函数,而该函数的返回值是一个指针。int *fun(int x,int y);注意:在调用指针函数时,需要一个同类型的指针来接收其函数的返回值。不过也可以将其返回值定义为 void*类型,在调用的时候强制转换返回值为自己想要的原创 2021-03-07 22:54:06 · 99 阅读 · 0 评论 -
析构函数和虚析构函数
析构函数和虚析构函数析构函数虚析构函数析构函数析构函数与构造函数对应,当对象结束其生命周期,系统会自动执行析构函数。它不能带任何参数,也没有返回值(包括void类型)。只能有一个析构函数,不能重载。如果一个类中有指针,且在使用的过程中动态的申请了内存,那么最好显示构造析构函数在销毁类之前,释放掉申请的内存空间,避免内存泄漏。析构函数的执行顺序:1)派生类本身的析构函数体;2)对象成员析构函数;3)基类析构函数。虚析构函数如果一个类的析构函数时虚函数,那么由它继承而来的所有子类的析构函数也是虚函数原创 2021-03-07 22:06:41 · 723 阅读 · 0 评论 -
c++中的引用和指针
c++中的引用和指针定义区别定义引用:引用是一个对象的别名,对引用的操作与对变量直接操作完全一样。指针:指针是存储对象的内存地址的一个特殊变量。区别指针引用有自己的一块空间只是一个别名本身有大小,用sizeof求出大小为4被引用对象的大小初始化可以为NULL必须初始化且必须是一个已有对象的引用,否则连编译都不能通过可以改变指向不可以改变指向作参数传递时,必须解引用才可以对对象进行操作可以直接改变对象的值有const指针没有const引用原创 2021-03-07 21:15:58 · 148 阅读 · 0 评论 -
智能指针
四个智能指针使用智能指针的原因C++智能指针使用智能指针的原因会存在这样一种情况:申请的空间在函数结束后忘记释放,造成内存泄漏。智能指针的作用是管理指针,智能指针是一个类,当超出了类的作用域时,类的析构函数会被自动调用,无需手动释放内存。C++智能指针C++里面的四个智能指针: auto_ptr, ==shared_ptr, weak_ptr, unique_ptr ==,其中后三个是c++11支持,并且第一个已经被11弃用。因此,c++11中智能指针包括以下3种:共享指针(shared_ptr),翻译 2021-03-07 17:39:06 · 311 阅读 · 0 评论 -
c++中四种cast转换
c++中四种cast转换1. const_cast2. static_cast3. dynamic_cast4. reinterpret_cast1. const_cast把const转为非const。2. static_cast用于各种隐式转换,比如非const转const,void*转指针等, static_cast能用于多态向上转化,如果向下转能成功但是不安全,结果未知;3. dynamic_cast用于动态类型转换。只能用于含有虚函数的类,用于类层次间的向上和向下转化。只能转指针或引用。翻译 2021-03-06 23:05:35 · 263 阅读 · 0 评论 -
static关键字的作用
static关键字的作用1. 全局静态变量2. 局部静态变量3. 静态函数4. 类的静态成员5. 类的成员函数1. 全局静态变量定义:在全局变量前加上关键字static;内存中的位置:静态存储区;初始化:未经初始化的全局静态变量会被自动初始化为0(自动对象的值是任意的,除非他被显式初始化);作用域:全局静态变量在声明他的文件之外是不可见的,准确地说是从定义之处开始,到文件结尾。2. 局部静态变量定义:在局部变量前加上关键字static;内存中的位置:静态存储区;初始化:未经初始化的局部静态原创 2021-03-06 22:35:38 · 14662 阅读 · 0 评论 -
C++中extern关键字使用
C++中extern关键字使用extern关键字使用extern混合编译C语言和C++extern关键字使用extern是一个关键字,它告诉编译器存在着一个变量或者一个函数,如果在当前编译语句的前面中没有找到相应的变量或者函数,也会在当前文件的后面或者其它文件中定义。那么定义在其他文件中的函数和变量,如何通过extern关键字调用呢? 首先,定义在其它文件中的函数和变量,可以使用两种方法调用:使用头文件调用,这时候,函数和变量必须在头文件中定义和声明。使用extern关键字调用,这时候函数和变量翻译 2021-03-06 22:02:16 · 723 阅读 · 0 评论