![](https://img-blog.csdnimg.cn/20201014180756757.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
c++
弟炜啊
这个作者很懒,什么都没留下…
展开
-
拷贝构造函数为什么要用引用和const
不加引用的话会一直递归调用下去加上const,防止对引用类型参数值的意外修改。原创 2021-09-22 18:34:37 · 107 阅读 · 0 评论 -
函数模板的底层
编译器并不是把函数模板处理成能够处理任意类的函数;编译器从函数模板通过具体类型产生不同 的函数;编译器会对函数模板进行两次编译:在声明的地方对模板代码本身进行编译 在调用的地方对参数替换后的代码进行编译。函数模板要被实例化后才能成为真正的函数,在使用函数模板的源文件中包含函数模板的头文件,如果该头文件中只有声明,没有定义,那编译器无法实例化该模板,最终导致链接错误。...原创 2021-09-22 18:31:01 · 104 阅读 · 0 评论 -
vector,list,deque容器的迭代器
vectorvector的迭代器并没有另外定义为一个模版类,而是直接 typedef value_type* iterator。 更可以看出 vector 的迭代器就是一个普通指针listlist 的迭代器本身是一个模板类这个迭代器的模板类包括:定义一些类型别名 定义一个 node 成员变量 必要的构造函数和重载了的操作符其中真正起作用的是 node 成员变量,它是指向 list 链表结构的结点的普通指针可以看出,list 的迭代器只是封装了 list node 的指针 ,并重原创 2021-09-22 18:28:34 · 121 阅读 · 0 评论 -
模板的实例化与具体化
实例化:模板本身不会生成函数或类定义,它只是一个用于生成函数或类的方案,编译器使用模板为特定类型生成函数或类定义的过程叫做模板的实例化。具体化:为模板中抽象的泛型指定具体的类型。它包含隐式实例化、显示实例化、显式具体化、部分具体化。隐式实例化编译器使用通用模板提供的处方生成具体的类定义,声明一个对象,指出所需的类型。编译器生成对象之前,不会生成类的隐式实例化:ArrayTP<double, 30> * pt; //指针pt,不会生成对象pt = new ArrayTP<.原创 2021-09-22 15:32:39 · 433 阅读 · 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<>class Test<int , char>{public:原创 2021-09-22 15:16:05 · 63 阅读 · 0 评论 -
类模板和函数模板的区别
类模板没有自动类型推导;类模板在模板参数列表中可以有默认参数;#include <iostream>#include <string>using namespace std; //类模板template <class TypeName, class TypeAge = int>class Person{public: Person(TypeName name, TypeAge age) { this->m_.原创 2021-09-22 15:33:50 · 125 阅读 · 0 评论 -
智能指针管理数组
shared_ptr默认是使用delete来释放管理的资源,delete只会调用第一个元素的析构函数要使用shared_ptr来管理数组,就需要需要自定义删除器int main(){ auto Deleter=[](Connection *connection){ delete[] connection; }; Connection* c1 = new Connection[2]{string("s1"), string("s2")}; // 新建管原创 2021-09-22 14:25:38 · 316 阅读 · 0 评论 -
Lambda表达式
Lambda 表达式的组成部分捕获子句(也称为 c + + 规范中的引导。 ) 参数列表可有可无. (也称为lambda 声明符) 可变规范可有可无. 异常规范可有可无. 尾随-返回类型可有可无. lambda 体。Capture字句Lambda 可以从周围范围访问或捕获变量。 Lambda 以捕获子句开头。 它指定捕获的变量以及捕获是通过值还是通过引用来捕获。 具有&前缀的变量通过引用访问,不包含它的变量通过值访问。空 capture 子句 [...原创 2021-09-16 14:13:58 · 174 阅读 · 0 评论 -
main函数开始前有哪些操作
设置栈指针为栈分配相关的位置,用来放一些局部变量和其他数据初始化static静态和global全局变量,即data段的内容把全局和静态变量初始化,放在相应的位置将未初始化部分的全局变量赋初值:数值型short,int,long等为0,bool为FALSE,指针为NULL,等等,即.bss段的内容将未设置初值的全局变量赋初值全局对象初始化,在main之前调用构造函数在main之前调用构造函数将main函数的参数,argc,argv等传递给main函数,然后才真正运行ma原创 2021-09-16 13:35:09 · 221 阅读 · 0 评论 -
哪些运算符不能重载
"."(类成员访问运算符) " .*"(类成员指针访问运算符) "::"(域运算符) "siezof"(长度运算符) " ?:"(条件运算符)4个“不能改变”不能改变运算符操作数的个数; 不能改变运算符原有的优先级; 不能改变运算符原有的结合性; 不能改变运算符原有的语法结构。...原创 2021-09-16 13:37:08 · 998 阅读 · 0 评论 -
move和forward
调用它两的主要目的一般都是将左值类型强制转换为右值类型从而在初始化其它对象时可以调用右值引用构造函数,减少内存的拷贝;forward完美转发语句:意思是将一个传进函数的参数原封不动的传递出去(这里的原封不动指的是如果传进来之前为右值,那么就以右值传出去,如果传进来是左值,那么就以左值传出去)。表现形式就是函数的形参声明为右值引用,该参数需要传递出去就要用forward();因为参数传进函数内部后,不管是左值还是右值在函数内部都有名字(即都是左值)这个时候需要用forward将左值转变为右值,那么原创 2021-09-16 13:36:43 · 266 阅读 · 0 评论 -
指针和引用的区别
指针和引用的定义和性质区别指针:指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元;而引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已。 引用不可以为空,当被创建的时候,必须初始化,而指针可以是空值,可以在任何时候被初始化。 可以有const指针,但是没有const引用; 指针可以有多级,但是引用只能是一级(int **p;合法 而 int &&a是不合法的) 指针的值可以为空,但是引用的值不能为NULL,并且引用在定义的时候必须初始化; 指原创 2021-09-15 18:30:12 · 172 阅读 · 0 评论 -
常量指针和指针常量的区别
指针常量就是指针本身是常量,换句话说,就是指针里面所存储的内容(内存地址)是常量,不能改变。但是,内存地址所对应的内容是可以通过指针改变的。 常量指针就是指向常量的指针,换句话说,就是指针指向的是常量,它指向的内容不能发生改变,不能通过指针来修改它指向的内容。但是,指针自身不是常量,它自身的值可以改变,从而指向另一个常量。...原创 2021-09-15 18:20:46 · 140 阅读 · 0 评论 -
c++的三个特性
继承、封装、多态继承一个对象直接使用另一个对象的属性和方法。优点减少重复的代码。 继承是多态的前提。 继承增加了类的耦合性。缺点继承在编译时刻就定义了,无法在运行时刻改变父类继承的实现; 父类通常至少定义了子类的部分行为,父类的改变都可能影响子类的行为; 如果继承下来的子类不适合解决新问题,父类必须重写或替换,那么这种依赖关系就限制了灵活性,最终限制了复用性。虚继承:为了解决多重继承中的二义性问题,它维护了一张虚基类表。多态C++中有两种多态,称为动多态(运行期多.原创 2021-09-15 17:23:04 · 62 阅读 · 0 评论 -
c++生成一个可执行文件经历了什么
预编译主要处理源代码文件中的以“#”开头的预编译指令。处理规则见下:删除所有的#define,展开所有的宏定义。 处理所有的条件预编译指令,如“#if”、“#endif”、“#ifdef”、“#elif”和“#else”。 处理“#include”预编译指令,将文件内容替换到它的位置,这个过程是递归进行的,文件中包含其他文件。 删除所有的注释,“//”和“/**/”。 保留所有的#pragma 编译器指令,编译器需要用到他们,如:#pragma once 是为了防止有文件被重复引用。 添加原创 2021-09-15 17:12:42 · 122 阅读 · 0 评论 -
为什么C比Python运行快
python的传统运行执行模式:录入的源代码转换为字节码,之后字节码在python虚拟机中运行。代码自动被编译,之后再解释成机器码在CPU中执行。 c编译器直接把c源代码编译成机器码。过程比python执行过程少了字节码生成和虚拟机执行字节码过程。...原创 2021-09-15 17:03:47 · 240 阅读 · 0 评论 -
C和C++的区别
主体不同C语言:是一门面向过程的、抽象化的通用程序设计语言,广泛应用于底层开发。 C++:是C语言的继承,它既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计。优势不同C语言:能以简易的方式编译、处理低级存储器。C语言是仅产生少量的机器语言以及不需要任何运行环境支持便能运行的高效率程序设计语言。 C++:不仅拥有计算机高效运行的实用性特征,同时还致力于提高大规模程序的编程质量与程序设计语言的问题描述能力。特点不同C语言:提供了许多低级处理的功能,原创 2021-09-15 17:02:25 · 214 阅读 · 0 评论 -
类对象创建过程
分配空间对于全局对象,静态对象以及分配在栈区域内的对象,对它们的内存分配是在编译阶段就完成了,而对于分配在堆区域内的对象,它们的分配是在运行是动态进行的。虚函数表指针赋值在构造函数的最开始,在进初始化列表之前,编译器会插入代码用当前正在被构造的类的虚表地址给虚表指针赋值。初始化对类对象的初始化,实际上是对类对象内的所有数据成员进行初始化。C++已经为我们提供了对类对象进行初始化的能力,我们可以通过实现构造函数的初始化列表来实现。初始化列表先于构造函数体内的代码执行赋值和类原创 2021-09-13 22:21:51 · 273 阅读 · 0 评论 -
vector扩容
为什么不每次增加一个固定大小的容量每次增加固定大小容量,则每次push_back的时间复杂度为O(n) 成倍增加容量,每次push_back的时间复杂度为O(1)原创 2021-09-13 18:40:05 · 106 阅读 · 0 评论 -
内存对齐相关知识
成员变量在类中的内存存储并不一定是连续的。它是按照编译器的设置,按照内存块来存储的,这个内存块大小的取值,就是内存对齐。规则第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。 在数据成员完成各自对齐之后,类(结构或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。#pragma pack(n)作为一个预编译指令用来设置多少个字节原创 2021-09-13 18:11:13 · 37 阅读 · 0 评论 -
c++内存管理
内存分区栈区(stack):栈的空间是连续的, 先进后出能保证不会产生内存碎片, 由高地址向低地址生长, 编译器自动分配和释放, 用来存放函数的参数值,局部变量的值等。操作方式类似于数据结构中的栈。栈用于维护函数调用的上下文,离开了栈函数调用就没法实现。 堆区(heap):堆则不同, 堆内存不一定是连续的. 分配方式是每次在空闲链表中遍历到第一个大于申请空间的节点,每次分配的空间大小一般不会正好等于申请的内存大小,所以频繁的new操作势必会产生大量的空间碎片 。 堆内存一般由程序员使用malloc、n原创 2021-09-12 17:56:19 · 54 阅读 · 0 评论 -
extern关键字详解
extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。此外extern也可用来进行链接指定。当它与"C"一起连用时,如: extern "C" void fun(int a, int b);则告诉编译器在编译fun这个函数名时按着C的规则去翻译相应的函数名而不是C++的 当extern不与"C"在一起修饰变量或函数时,如在头文件中: extern int g_Int;它的作用就是声明函数或全局变量的作用范围的关键字,其声明的函数.原创 2021-09-12 16:43:16 · 294 阅读 · 0 评论 -
动态链接和静态链接
静态连接库就是把(lib)文件中用到的函数代码直接链接进目标程序,程序运行的时候不再需要其它的库文件动态链接就是把调用的函数所在文件模块(DLL)和调用函数在文件中的位置等信息链接进目标程序,程序运行的时候再从DLL中寻找相应函数代码,因此需要相应DLL文件的支持。动态链接库的调用方式隐式调用我们在生成动态链接库dll后,还会生成一个静态链接库lib文件,隐式调用时需要dll和lib两种文件将dll放到:可执行程序所在目录、Windows目录 设置项目属性--vc++目录--库目录为l原创 2021-09-12 16:39:11 · 64 阅读 · 0 评论 -
Extern “C”
extern "C"的主要作用就是为了能够正确实现C++代码调用其他C语言代码。加上extern "C"后,会指示编译器这部分代码按C语言(而不是C++)的方式进行编译。C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般只包括函数名由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名...原创 2021-09-11 13:02:18 · 33 阅读 · 0 评论 -
类的相关知识点
类中的成员变量的初始化类的初始化表的初始化顺序是根据成员变量的声明顺序来执行的,而不是按照初始化列表的顺序。如果我们要按初始化列表的顺序来进行初始化,那么我们就得记住这个顺序,以便在析构时决定析构的顺序。所以C++就选择了简单的点的方法,按成员变量出现的顺序来初始化。使用初始化列表的优点C++中, 类成员的初始化在初始化列表中完成, 先于构造函数执行即成员真正的初始化发生在初始化列表中, 而不是构造函数体中提高效率假如存在string类型的类成员,在初始化时会调用他的默认构造原创 2021-09-11 13:02:00 · 81 阅读 · 0 评论 -
new和malloc
malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。 由与malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。 new出来的指针是直接带类型信息的。而malloc返回的都是void*指针。 使用new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算。而malloc则需要显式地指出所需内存的尺寸。 new内存分配失败时,会抛出原创 2021-09-11 13:01:27 · 262 阅读 · 0 评论 -
智能指针知识点
shared_ptr数据结构shared_ptr 是引用计数型(reference counting)智能指针,几乎所有的实现都采用在堆(heap)上放个计数值(count)的办法。具体来说,shared_ptr<Foo> 包含两个成员,一个是指向 Foo 的指针 ptr,另一个是 ref_count 指针,指向堆上的 ref_count 对象。ref_count 对象有多个成员,具体的数据结构如图所示,其中 deleter 和 allocator 是可选的。如果再执行 shar原创 2021-09-11 13:01:10 · 105 阅读 · 0 评论 -
移动语义相关知识
移动构造函数移动构造函数与拷贝构造函数的区别是,拷贝构造的参数是const MyString& str,是常量左值引用,而移动构造的参数是MyString&& str,是右值引用,而MyString("hello")是个临时对象,是个右值,优先进入移动构造函数而不是拷贝构造函数。移动构造函数与拷贝构造不同,它并不是重新分配一块新的空间,将要拷贝的对象复制过来,而是"偷"了过来,将自己的指针指向别人的资源,然后将别人的指针修改为nullptr,这一原创 2021-09-10 21:12:16 · 34 阅读 · 0 评论 -
右值引用相关知识
右值引用指的是以引用传递(而非值传递)的方式使用 C++ 右值,用 "&&" 表示。左值:存储在内存中、有明确存储地址(可寻址)的数据,表达式结束后依然存在的持久化对象右值:可以提供数据值的数据(不一定可以寻址,例如存储于寄存器中的数据),表达式结束时就不再存在的临时对象。如非引用返回的函数返回的临时变量值;一些运算表达式,如1+2产生的临时变量;不跟对象关联的字面量值,如2,'c',true,"hello";和声明左值引用一样,右值引用也必须立即进行初始化操作,且只能使用右原创 2021-09-10 21:05:25 · 143 阅读 · 0 评论 -
完美转发的知识
std::forward被称为完美转发,它的作用是保持原来的值属性不变。如果原来的值是左值,经std::forward处理后该值还是左值;如果原来的值是右值,经std::forward处理后它还是右值。forward实现原理template <typename T>T&& forward(typename std::remove_reference<T>::type& param){ return static_cast<T&a原创 2021-09-10 20:50:57 · 91 阅读 · 0 评论