07 2021 档案

C++ 中的 inline 用法
摘要:1、引入 inline 关键字的原因 在 c/c++ 中,为了解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题,特别的引入了 inline 修饰符,表示为内联函数。 栈空间就是指放置程序的局部数据(也就是函数内数据)的内存空间。 在系统下,栈空间是有限的,假如频繁大量的使用就会造成因栈空间不足 阅读全文
posted @ 2021-07-29 22:38 超人不会灰啊 阅读(156) 评论(0) 推荐(0)
27、final和override关键字
摘要:override 当在父类中使用了虚函数时候,你可能需要在某个子类中对这个虚函数进行重写,以下方法都可以: 如果不使用override,当你手一抖,将foo()写成了f00()会怎么样呢?结果是编译器并不会报错,因为 它并不知道你的目的是重写虚函数,而是把它当成了新的函数。如果这个虚函数很重要的话, 阅读全文
posted @ 2021-07-29 22:07 超人不会灰啊 阅读(84) 评论(0) 推荐(0)
详解C/C++中volatile关键字
摘要:一、volatile介绍 volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致 阅读全文
posted @ 2021-07-29 21:28 超人不会灰啊 阅读(285) 评论(0) 推荐(0)
38、hashtable中解决冲突有哪些方法?
摘要:记住前三个: 线性探测 使用hash函数计算出的位置如果已经有元素占用了,则向后依次寻找,找到表尾则回到表头,直到找 到一个空位 开链 每个表格维护一个list,如果hash函数计算出的格子相同,则按顺序存在这个list中 再散列 发生冲突时使用另一种hash函数再计算一个地址,直到不冲突 二次探测 阅读全文
posted @ 2021-07-28 22:52 超人不会灰啊 阅读(132) 评论(0) 推荐(0)
37、STL中unordered_map和map的区别和应用场景
摘要:map支持键值的自动排序,底层机制是红黑树,红黑树的查询和维护时间复杂度均为$O(logn)$,但是空间占用比较大,因为每个节点要保持父节点、孩子节点及颜色的信息 unordered_map是C++ 11新添加的容器,底层机制是哈希表,通过hash函数计算元素位置,其查询时间复杂度为O(1),维护时 阅读全文
posted @ 2021-07-28 22:50 超人不会灰啊 阅读(617) 评论(0) 推荐(0)
36、set和map的区别,multimap和multiset的区别
摘要:set只提供一种数据类型的接口,但是会将这一个元素分配到key和value上,而且它的compare_function用 的是 identity()函数,这个函数是输入什么输出什么,这样就实现了set机制,set的key和value其实是一样 的了。其实他保存的是两份元素,而不是只保存一份元素 ma 阅读全文
posted @ 2021-07-28 22:48 超人不会灰啊 阅读(274) 评论(0) 推荐(0)
35、STL中map的实现
摘要:map的特性是所有元素会根据键值进行自动排序。map中所有的元素都是pair,拥有键值(key)和实值 (value)两个部分,并且不允许元素有相同的key 一旦map的key确定了,那么是无法修改的,但是可以修改这个key对应的value,因此map的迭代器既不 是constant iterato 阅读全文
posted @ 2021-07-28 22:43 超人不会灰啊 阅读(501) 评论(0) 推荐(0)
34、STL中set的实现?
摘要:STL中的容器可分为序列式容器(sequence)和关联式容器(associative),set属于关联式容器。 set的特性是,所有元素都会根据元素的值自动被排序(默认升序),set元素的键值就是实值,实值就是 键值,set不允许有两个相同的键值 set不允许迭代器修改元素的值,其迭代器是一种co 阅读全文
posted @ 2021-07-28 22:28 超人不会灰啊 阅读(168) 评论(0) 推荐(0)
33、STL中的priority_queue的实现
摘要:priority_queue,优先队列,是一个拥有权值观念的queue,它跟queue一样是顶部入口,底部出口,在插 入元素时,元素并非按照插入次序排列,它会自动根据权值(通常是元素的实值)排列,权值最高,排 在最前面,如下图所示。 默认情况下,priority_queue使用一个max-heap完 阅读全文
posted @ 2021-07-28 22:20 超人不会灰啊 阅读(112) 评论(0) 推荐(0)
32、STL中的heap的实现
摘要:heap(堆)并不是STL的容器组件,是priority queue(优先队列)的底层实现机制,因为binary max heap(大根堆)总是最大值位于堆的根部,优先级最高。 binary heap本质是一种complete binary tree(完全二叉树),整棵binary tree除了最底 阅读全文
posted @ 2021-07-28 22:05 超人不会灰啊 阅读(119) 评论(0) 推荐(0)
31、STL中stack和queue的实现
摘要:stack stack(栈)是一种先进后出(First In Last Out)的数据结构,只有一个入口和出口,那就是栈顶,除了 获取栈顶元素外,没有其他方法可以获取到内部的其他元素,其结构图如下: stack这种单向开口的数据结构很容易由双向开口的deque和list形成,只需要根据stack的性 阅读全文
posted @ 2021-07-28 21:40 超人不会灰啊 阅读(105) 评论(0) 推荐(0)
30、STL中的deque的实现
摘要:vector是单向开口(尾部)的连续线性空间,deque则是一种双向开口的连续线性空间,虽然vector也可 以在头尾进行元素操作,但是其头部操作的效率十分低下(主要是涉及到整体的移动) deque和vector的最大差异一个是deque运行在常数时间内对头端进行元素操作,二是deque没有容量的概 阅读全文
posted @ 2021-07-28 21:28 超人不会灰啊 阅读(123) 评论(0) 推荐(0)
29、STL中list的实现
摘要:相比于vector的连续线型空间,list显得复杂许多,但是它的好处在于插入或删除都只作用于一个元素空 间,因此list对空间的运用是十分精准的,对任何位置元素的插入和删除都是常数时间。list不能保证节 点在存储空间中连续存储,也拥有迭代器,迭代器的“++”、“--”操作对于的是指针的操作,lis 阅读全文
posted @ 2021-07-28 16:27 超人不会灰啊 阅读(77) 评论(0) 推荐(0)
28、STL中slist的实现
摘要:list是双向链表,而slist(single linked list)是单向链表,它们的主要区别在于:前者的迭代器是双向的 Bidirectional iterator,后者的迭代器属于单向的Forward iterator。虽然slist的很多功能不如list灵活,但是 其所耗用的空间更小,操作 阅读全文
posted @ 2021-07-28 16:09 超人不会灰啊 阅读(127) 评论(0) 推荐(0)
27、STL中vector的实现
摘要:vector是一种序列式容器,其数据安排以及操作方式与array非常类似,两者的唯一差别就是对于空间运 用的灵活性,众所周知,array占用的是静态空间,一旦配置了就不可以改变大小,如果遇到空间不足的 情况还要自行创建更大的空间,并手动将数据拷贝到新的空间中,再把原来的空间释放。vector则使用 阅读全文
posted @ 2021-07-28 16:06 超人不会灰啊 阅读(83) 评论(0) 推荐(0)
26、STL中迭代器失效的情况有哪些?
摘要:以vector为例: 插入元素: 1、尾后插入:size < capacity时,首迭代器不失效尾迭代失效(未重新分配空间),size == capacity时, 所有迭代器均失效(需要重新分配空间)。 2、中间插入:中间插入:size < capacity时,首迭代器不失效但插入元素之后所有迭代器 阅读全文
posted @ 2021-07-28 16:05 超人不会灰啊 阅读(223) 评论(0) 推荐(0)
24、vector的增加删除都是怎么做的?为什么是1.5或者是2倍?
摘要:1) 新增元素:vector通过一个连续的数组存放元素,如果集合已满,在新增数据的时候,就要分配一块 更大的内存,将原来的数据复制过来,释放之前的内存,在插入新增的元素; 2) 对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器就都失效了 ; 3) 初始时刻vector的 阅读全文
posted @ 2021-07-28 15:55 超人不会灰啊 阅读(234) 评论(0) 推荐(0)
22、STL中hash_map扩容发生什么?
摘要:1) hash table表格内的元素称为桶(bucket),而由桶所链接的元素称为节点(node),其中存入桶元素的容 器为stl本身很重要的一种序列式容器——vector容器。之所以选择vector为存放桶元素的基础容器,主要 是因为vector容器本身具有动态扩容能力,无需人工干预。 2) 向 阅读全文
posted @ 2021-07-28 15:47 超人不会灰啊 阅读(380) 评论(0) 推荐(0)
21、STL中的allocator、deallocator
摘要:1) 第一级配置器直接使用malloc()、free()和relloc(),第二级配置器视情况采用不同的策略:当配置区块 超过128bytes时,视之为足够大,便调用第一级配置器;当配置器区块小于128bytes时,为了降低额外负 担,使用复杂的内存池整理方式,而不再用一级配置器; 2) 第二级配置 阅读全文
posted @ 2021-07-28 15:43 超人不会灰啊 阅读(172) 评论(0) 推荐(0)
20、 STL中list与queue之间的区别
摘要:1) list不再能够像vector一样以普通指针作为迭代器,因为其节点不保证在存储空间中连续存在; 2) list插入操作和结合才做都不会造成原有的list迭代器失效; 3) list不仅是一个双向链表,而且还是一个环状双向链表,所以它只需要一个指针; 4) list不像vector那样有可能在空 阅读全文
posted @ 2021-07-28 15:40 超人不会灰啊 阅读(768) 评论(0) 推荐(0)
19、map中[]与find的区别?
摘要:1) map的下标运算符[]的作用是:将关键码作为下标去执行查找,并返回对应的值;如果不存在这个关 键码,就将一个具有该关键码和值类型的默认值的项插入这个map。 2) map的find函数:用关键码执行查找,找到了返回该位置的迭代器;如果不存在这个关键码,就返回 尾迭代器。 阅读全文
posted @ 2021-07-28 15:26 超人不会灰啊 阅读(271) 评论(0) 推荐(0)
18、vector越界访问下标,map越界访问下标?vector删除元素时会不会释放空间?
摘要:1) 通过下标访问vector中的元素时会做边界检查,确保访问不会出现错误。 2) map的下标运算符[]的作用是:将key作为下标去执行查找,并返回相应的值;如果不存在这个key, 就将一个具有该key和value的某人值插入这个map。 3) erase()函数,只能删除内容,不能改变容量大小; 阅读全文
posted @ 2021-07-28 15:22 超人不会灰啊 阅读(423) 评论(0) 推荐(0)
17、STL中unordered_map(hash_map)和map的区别,hash_map如何解决 冲突以及扩容
摘要:1) unordered_map和map类似,都是存储的key-value的值,可以通过key快速索引到value。不同的是 unordered_map 不会根据key的大小进行排序。 2) 存储时是根据key的hash值判断元素是否相同,即unordered_map内部元素是无序的,而map中的元 阅读全文
posted @ 2021-07-28 14:59 超人不会灰啊 阅读(541) 评论(0) 推荐(0)
16、map插入方式有哪几种?
摘要: 阅读全文
posted @ 2021-07-28 14:28 超人不会灰啊 阅读(118) 评论(0) 推荐(0)
15、如何在共享内存上使用STL标准库?
摘要:1) 想像一下把STL容器,例如map, vector, list等等,放入共享内存中,IPC一旦有了这些强大的通用数据 结构做辅助,无疑进程间通信的能力一下子强大了很多。 我们没必要再为共享内存设计其他额外的数据结构,另外,STL的高度可扩展性将为IPC所驱使。STL容 器被良好的封装,默认情况下 阅读全文
posted @ 2021-07-28 14:27 超人不会灰啊 阅读(443) 评论(0) 推荐(0)
14、map、set是怎么实现的,红黑树是怎么能够同时实现这两种容器? 为 什么使用红黑树?
摘要:1) 他们的底层都是以红黑树的结构实现,因此插入删除等操作都在O(logn时间内完成,因此可以完成高 效的插入删除; 2) 在这里我们定义了一个模版参数,如果它是key那么它就是set,如果它是map,那么它就是map;底 层是红黑树,实现map的红黑树的节点数据类型是key+value,而实现se 阅读全文
posted @ 2021-07-28 11:07 超人不会灰啊 阅读(213) 评论(0) 推荐(0)
13、STL迭代器如何实现
摘要:1、 迭代器是一种抽象的设计理念,通过迭代器可以在不了解容器内部原理的情况下遍历容器,除此之外,STL中迭代器一个最重要的作用就是作为容器与STL算法的粘合剂。 2、 迭代器的作用就是提供一个遍历容器内部所有元素的接口,因此迭代器内部必须保存一个与容器相 关联的指针,然后重载各种运算操作来遍历,其中 阅读全文
posted @ 2021-07-28 11:03 超人不会灰啊 阅读(100) 评论(0) 推荐(0)
12、容器内部删除一个元素
摘要:1) 顺序容器(序列式容器,比如vector、deque) erase迭代器不仅使所指向被删除的迭代器失效,而且使被删元素之后的所有迭代器失效(list除外),所以 不能使用erase(it++)的方式,但是erase的返回值是下一个有效迭代器; It = c.erase(it); 2) 关联容器( 阅读全文
posted @ 2021-07-28 10:52 超人不会灰啊 阅读(154) 评论(0) 推荐(0)
11、Vector如何释放空间?
摘要:由于vector的内存占用空间只增不减,比如你首先分配了10,000个字节,然后erase掉后面9,999个,留下 一个有效元素,但是内存占用仍为10,000个。所有内存空间是在vector析构时候才能被系统回收。 empty()用来检测容器是否为空的,clear()可以清空所有元素。但是即使cle 阅读全文
posted @ 2021-07-28 10:46 超人不会灰啊 阅读(327) 评论(0) 推荐(0)
10、STL 中vector删除其中的元素,迭代器如何变化?为什么是两倍扩 容?释放空间?
摘要:size()函数返回的是已用空间大小,capacity()返回的是总空间大小,capacity()-size()则是剩余的可用空间大小。当size()和capacity()相等,说明vector目前的空间已被用完,如果再添加新元素,则会引起vector空 间的动态增长。 由于动态增长会引起重新分配内 阅读全文
posted @ 2021-07-28 10:42 超人不会灰啊 阅读(403) 评论(0) 推荐(0)
9、 vector与list的区别与应用?怎么找某vector或者list的倒数第二个元素
摘要:1) vector数据结构 vector和数组类似,拥有一段连续的内存空间,并且起始地址不变。因此能高效的进行随机存取,时间 复杂度为o(1);但因为内存空间是连续的,所以在进行插入和删除操作时,会造成内存块的拷贝,时间复 杂度为o(n)。另外,当数组中内存空间不够时,会重新申请一块内存空间并进行内 阅读全文
posted @ 2021-07-28 10:28 超人不会灰啊 阅读(442) 评论(0) 推荐(1)
8、STL的两级空间配置器
摘要:1、首先明白为什么需要二级空间配置器? 我们知道动态开辟内存时,要在堆上申请,但若是我们需要 频繁的在堆开辟释放内存,则就会在堆上造成很多外部碎片,浪费了内存空间; 每次都要进行调用malloc、free函数等操作,使空间就会增加一些附加信息,降低了空间利用率; 随着外部碎片增多,内存分配器在找不到 阅读全文
posted @ 2021-07-28 00:39 超人不会灰啊 阅读(286) 评论(0) 推荐(1)
186、说一下C++左值引用和右值引用
摘要:C++11正是通过引入右值引用来优化性能,具体来说是通过移动语义来避免无谓拷贝的问题,通过 move语义来将临时生成的左值中的资源无代价的转移到另外一个对象中去,通过完美转发来解决不能 按照参数实际类型来转发的问题(同时,完美转发获得的一个好处是可以实现移动语义)。 1) 在C++11中所有的值必属 阅读全文
posted @ 2021-07-21 01:01 超人不会灰啊 阅读(206) 评论(0) 推荐(0)
180、C++从代码到可执行程序经历了什么?
摘要:(1)预编译 主要处理源代码文件中的以“#”开头的预编译指令。处理规则见下: 1. 删除所有的#define,展开所有的宏定义。 2. 处理所有的条件预编译指令,如“#if”、“#endif”、“#ifdef”、“#elif”和“#else”。 3. 处理“#include”预编译指令,将文件内容替 阅读全文
posted @ 2021-07-21 00:59 超人不会灰啊 阅读(82) 评论(0) 推荐(0)
177、你知道回调函数吗?它的作用?
摘要:1) 当发生某种事件时,系统或其他函数将会自动调用你定义的一段函数; 2) 回调函数就相当于一个中断处理函数,由系统在符合你设定的条件时自动调用。为此,你需要做三 件事:1,声明;2,定义;3,设置触发条件,就是在你的函数中把你的回调函数名称转化为地址作为 一个参数,以便于系统调用; 3) 回调函数 阅读全文
posted @ 2021-07-20 23:37 超人不会灰啊 阅读(472) 评论(0) 推荐(0)
176、成员函数里memset(this,0,sizeof(*this))会发生什么
摘要:1) 有时候类里面定义了很多int,char,struct等c语言里的那些类型的变量,我习惯在构造函数中将它们初 始化为0,但是一句句的写太麻烦,所以直接就memset(this, 0, sizeof *this);将整个对象的内存全部置 为0。对于这种情形可以很好的工作,但是下面几种情形是不可以这 阅读全文
posted @ 2021-07-20 23:36 超人不会灰啊 阅读(132) 评论(0) 推荐(0)
171、main函数的返回值有什么值得考究之处吗?
摘要:程序运行过程入口点main函数,main()函数返回值类型必须是int,这样返回值才能传递给程序激活 者(如操作系统)表示程序正常退出。 main(int args, char **argv) 参数的传递。参数的处理,一般会调用getopt()函数处理,但实践 中,这仅仅是一部分,不会经常用到的技能 阅读全文
posted @ 2021-07-20 23:33 超人不会灰啊 阅读(127) 评论(0) 推荐(0)
169、 如何禁止程序自动生成拷贝构造函数?
摘要:1) 为了阻止编译器默认生成拷贝构造函数和拷贝赋值函数,我们需要手动去重写这两个函数,某些情 况下,为了避免调用拷贝构造函数和拷贝赋值函数,我们需要将他们设置成private,防止被调用。 2) 类的成员函数和friend函数还是可以调用private函数,如果这个private函数只声明不定义,则 阅读全文
posted @ 2021-07-20 23:31 超人不会灰啊 阅读(346) 评论(0) 推荐(0)
168、如何阻止一个类被实例化?有哪些方法?
摘要:1) 将类定义为抽象基类或者将构造函数声明为private; 2) 不允许类外部创建类对象,只能在类内部创建对象 阅读全文
posted @ 2021-07-20 23:29 超人不会灰啊 阅读(269) 评论(0) 推荐(0)
164、哪些函数不能是虚函数?把你知道的都说一说
摘要:1) 构造函数,构造函数初始化对象,派生类必须知道基类函数干了什么,才能进行构造;当有虚函数 时,每一个类有一个虚表,每一个对象有一个虚表指针,虚表指针在构造函数中初始化; 2) 内联函数,内联函数表示在编译阶段进行函数体的替换操作,而虚函数意味着在运行期间进行类型确定,所以内联函数不能是虚函数; 阅读全文
posted @ 2021-07-20 23:27 超人不会灰啊 阅读(261) 评论(0) 推荐(0)
163、一个类中的全部构造函数的扩展过程是什么?
摘要:1) 记录在成员初始化列表中的数据成员初始化操作会被放在构造函数的函数体内,并与成员的声明顺 序为顺序; 2) 如果一个成员并没有出现在成员初始化列表中,但它有一个默认构造函数,那么默认构造函数必须 被调用; 3) 如果class有虚表,那么它必须被设定初值; 4) 所有上一层的基类构造函数必须被调 阅读全文
posted @ 2021-07-20 23:22 超人不会灰啊 阅读(181) 评论(0) 推荐(0)
162、构造函数的执行顺序是什么?
摘要:1) 在派生类构造函数中,所有的虚基类及上一层基类的构造函数调用; 2) 对象的vptr被初始化; 3) 如果有成员初始化列表,将在构造函数体内扩展开来,这必须在vptr被设定之后才做; 4) 执行程序员所提供的代码; 阅读全文
posted @ 2021-07-20 23:21 超人不会灰啊 阅读(223) 评论(0) 推荐(1)
161、成员初始化列表会在什么时候用到?它的调用过程是什么?
摘要:1) 当初始化一个引用成员变量时; 2) 初始化一个const成员变量时; 3) 当调用一个基类的构造函数,而构造函数拥有一组参数时; 4) 当调用一个成员类的构造函数,而他拥有一组参数; 5) 编译器会一一操作初始化列表,以适当顺序在构造函数之内安插初始化操作,并且在任何显示用户 代码前。list 阅读全文
posted @ 2021-07-20 23:18 超人不会灰啊 阅读(236) 评论(0) 推荐(0)
160、那什么时候需要合成拷贝构造函数呢?
摘要:有三种情况会以一个对象的内容作为另一个对象的初值: 1) 对一个对象做显示的初始化操作,X xx = x; 2) 当对象被当做参数交给某个函数时; 3) 当函数传回一个类对象时; 1) 如果一个类没有拷贝构造函数,但是含有一个类类型的成员变量,该类型含有拷贝构造函数,此时 编译器会为该类合成一个拷贝 阅读全文
posted @ 2021-07-20 23:16 超人不会灰啊 阅读(144) 评论(0) 推荐(0)
159、 什么时候合成构造函数?都说一说,你知道的都说一
摘要:1) 如果一个类没有任何构造函数,但他含有一个成员对象,该成员对象含有默认构造函数,那么编译 器就为该类合成一个默认构造函数,因为不合成一个默认构造函数那么该成员对象的构造函数不能调 用; 2) 没有任何构造函数的类派生自一个带有默认构造函数的基类,那么需要为该派生类合成一个构造函 数,只有这样基类 阅读全文
posted @ 2021-07-20 23:12 超人不会灰啊 阅读(91) 评论(0) 推荐(0)
158、移动构造函数听说过吗?说说
摘要:1) 有时候我们会遇到这样一种情况,我们用对象a初始化对象b后对象a我们就不在使用了,但是对象a 的空间还在呀(在析构之前),既然拷贝构造函数,实际上就是把a对象的内容复制一份到b中,那么为 什么我们不能直接使用a的空间呢?这样就避免了新的空间的分配,大大降低了构造的成本。这就是移 动构造函数设计的 阅读全文
posted @ 2021-07-20 23:09 超人不会灰啊 阅读(84) 评论(0) 推荐(0)
157、类对象的大小受哪些因素影响?
摘要:1) 类的非静态成员变量大小,静态成员不占据类的空间,成员函数也不占据类的空间大小; 2) 内存对齐另外分配的空间大小,类内的数据也是需要进行内存对齐操作的; 3) 虚函数的话,会在类对象插入vptr指针,加上指针大小; 4) 当该该类是某类的派生类,那么派生类继承的基类部分的数据成员也会存在在派生 阅读全文
posted @ 2021-07-20 23:00 超人不会灰啊 阅读(170) 评论(0) 推荐(0)
153、你知道静态绑定和动态绑定吗?讲讲?
摘要:1) 对象的静态类型:对象在声明时采用的类型。是在编译期确定的。 2) 对象的动态类型:目前所指对象的类型。是在运行期决定的。对象的动态类型可以更改,但是静态 类型无法更改。 3) 静态绑定:绑定的是对象的静态类型,某特性(比如函数依赖于对象的静态类型,发生在编译期。 4) 动态绑定:绑定的是对象的 阅读全文
posted @ 2021-07-20 22:59 超人不会灰啊 阅读(233) 评论(0) 推荐(0)
152、this指针调用成员变量时,堆栈会发生什么变化?
摘要:当在类的非静态成员函数访问类的非静态成员时,编译器会自动将对象的地址传给作为隐含参数传递给函数,这个隐含参数就是this指针。 即使你并没有写this指针,编译器在链接时也会加上this的,对各成员的访问都是通过this的。 例如你建立了类的多个对象时,在调用类的成员函数时,你并不知道具体是哪个对象 阅读全文
posted @ 2021-07-20 22:53 超人不会灰啊 阅读(290) 评论(0) 推荐(0)
151、静态函数能定义为虚函数吗?常函数呢?说说你的理解
摘要:1、static成员不属于任何类对象或类实例,所以即使给此函数加上virutal也是没有任何意义的。 2、静态与非静态成员函数之间有一个主要的区别,那就是静态成员函数没有this指针。 虚函数依靠vptr和vtable来处理。vptr是一个指针,在类的构造函数中创建生成,并且只能用this指针来 访 阅读全文
posted @ 2021-07-20 22:48 超人不会灰啊 阅读(364) 评论(0) 推荐(0)
150、你什么情况用指针当参数,什么时候用引用,为什么?
摘要:1) 使用引用参数的主要原因有两个: 程序员能修改调用函数中的数据对象 通过传递引用而不是整个数据–对象,可以提高程序的运行速度 2) 一般的原则: 对于使用引用的值而不做修改的函数: 如果数据对象很小,如内置数据类型或者小型结构,则按照值传递; 如果数据对象是数组,则使用指针(唯一的选择),并且指 阅读全文
posted @ 2021-07-20 22:47 超人不会灰啊 阅读(202) 评论(0) 推荐(0)
149、你知道空类的大小是多少吗?
摘要:1) C++空类的大小不为0,不同编译器设置不一样,vs设置为1; 2) C++标准指出,不允许一个对象(当然包括类对象)的大小为0,不同的对象不能具有相同的地址; 3) 带有虚函数的C++类大小不为1,因为每一个对象会有一个vptr指向虚函数表,具体大小根据指针大小确定; 4) C++中要求对于类 阅读全文
posted @ 2021-07-20 22:43 超人不会灰啊 阅读(196) 评论(0) 推荐(0)
148、为什么拷贝构造函数必须传引用不能传值?
摘要:1) 拷贝构造函数的作用就是用来复制对象的,在使用这个对象的实例来初始化这个对象的一个新的实 例。 2) 参数传递过程到底发生了什么? 将地址传递和值传递统一起来,归根结底还是传递的是"值"(地址也是值,只不过通过它可以找到另一 个值)! i)值传递: 对于内置数据类型的传递时,直接赋值拷贝给形参( 阅读全文
posted @ 2021-07-20 22:37 超人不会灰啊 阅读(421) 评论(0) 推荐(0)
147、你知道const char* 与string之间的关系是什么吗?
摘要:1) string 是c++标准库里面其中一个,封装了对字符串的操作,实际操作过程我们可以用const char*给 string类初始化 a) string转const char*string s = “abc”;const char* c_s = s.c_str();b) const char* 阅读全文
posted @ 2021-07-20 22:16 超人不会灰啊 阅读(454) 评论(0) 推荐(0)
146、C++中标准库是什么?
摘要:1) C++ 标准库可以分为两部分: 标准函数库: 这个库是由通用的、独立的、不属于任何类的函数组成的。函数库继承自 C 语言。 面向对象类库: 这个库是类及其相关函数的集合。 2) 输入/输出 I/O、字符串和字符处理、数学、时间、日期和本地化、动态分配、其他、宽字符函数 3) 标准的 C++ I 阅读全文
posted @ 2021-07-20 22:11 超人不会灰啊 阅读(244) 评论(0) 推荐(0)
144、volatile关键字的作用?
摘要:volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比 如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再 进行优化,从而可以提供对特殊地址的稳定访问。声明时语法:int volatile vInt; 当要求使用 v 阅读全文
posted @ 2021-07-20 22:08 超人不会灰啊 阅读(68) 评论(0) 推荐(0)
数组指针和指针数组的区别
摘要:数组指针(也称行指针)定义 int (*p)[n];()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。 如要将二维数组赋给一指针,应这样赋值:int a[3][4];int (*p)[4]; // 阅读全文
posted @ 2021-07-20 22:02 超人不会灰啊 阅读(96) 评论(0) 推荐(0)
143、程序在执行int main(int argc, char *argv[])时的内存结构,你了解吗?
摘要:参数的含义是程序在命令行下运行的时候,需要输入argc 个参数,每个参数是以char 类型输入的,依 次存在数组里面,数组是 argv[],所有的参数在指针 char * 指向的内存中,数组的中元素的个数为 argc 个,第一个参数为程序的名称。 阅读全文
posted @ 2021-07-20 22:00 超人不会灰啊 阅读(141) 评论(0) 推荐(0)
142、你知道strcpy和memcpy的区别是什么吗?
摘要:1、复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。 2、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。 3、用途不同。通常在复制字符串 阅读全文
posted @ 2021-07-20 21:52 超人不会灰啊 阅读(179) 评论(0) 推荐(0)
140、在成员函数中调用delete this会出现什么问题?对象还可以使用吗?
摘要:1、在类对象的内存空间中,只有数据成员和虚函数表指针,并不包含代码内容,类的成员函数单独放 在代码段中。在调用成员函数时,隐含传递一个this指针,让成员函数知道当前是哪个对象在调用它。 当调用delete this时,类对象的内存空间被释放。在delete this之后进行的其他任何函数调用,只要 阅读全文
posted @ 2021-07-20 21:49 超人不会灰啊 阅读(207) 评论(0) 推荐(0)
139、模板和实现一定要写在一个文件里面?为什么?
摘要:因为在编译时模板并不能生成真正的二进制代码,而是在编译调用模板类或函数的CPP文件时才会去找 对应的模板声明和实现,在这种情况下编译器是不知道实现模板类或函数的CPP文件的存在,所以它只 能找到模板类或函数的声明而找不到实现,而只好创建一个符号寄希望于链接程序找地址。 但模板类或函数的实现并不能被编 阅读全文
posted @ 2021-07-20 21:38 超人不会灰啊 阅读(309) 评论(0) 推荐(0)
137、迭代器:++it、it++哪个好,为什么
摘要:1) 前置返回一个引用,后置返回一个对象 2) 前置不会产生临时对象,后置必须产生临时对象,临时对象会导致效率降低 阅读全文
posted @ 2021-07-20 00:48 超人不会灰啊 阅读(170) 评论(0) 推荐(0)
136、多继承的优缺点,作为一个开发者怎么看待多继承
摘要:1) C++允许为一个派生类指定多个基类,这样的继承结构被称做多重继承。 2) 多重继承的优点很明显,就是对象可以调用多个基类中的接口; 3) 如果派生类所继承的多个基类有相同的基类,而派生类对象需要调用这个祖先类的接口方法,就会容 易出现二义性 4) 加上全局符确定调用哪一份拷贝。比如pa.Aut 阅读全文
posted @ 2021-07-20 00:40 超人不会灰啊 阅读(338) 评论(0) 推荐(0)
135、 虚函数的内存结构,那菱形继承的虚函数内存结构呢
摘要:菱形继承的定义是:两个子类继承同一父类,而又有子类同时继承这两个子类。例如a,b两个类同时继 承c,但是又有一个d类同时继承a,b类。 阅读全文
posted @ 2021-07-20 00:38 超人不会灰啊 阅读(110) 评论(0) 推荐(0)
134、隐式转换,如何消除隐式转换?
摘要:1、C++的基本类型中并非完全的对立,部分数据类型之间是可以进行隐式转换的。所谓隐式转换,是指不需要用户干预,编译器私下进行的类型转换行为。很多时候用户可能都不知道进行了哪些转换 2、C++面向对象的多态特性,就是通过父类的类型实现对子类的封装。通过隐式转换,你可以直接将 一个子类的对象使用父类的类 阅读全文
posted @ 2021-07-20 00:36 超人不会灰啊 阅读(417) 评论(0) 推荐(0)
133、说一下你理解的 ifdef endif代表着什么?
摘要:1) 一般情况下,源程序中所有的行都参加编译。但是有时希望对其中一部分内容只在满足一定条件才 进行编译,也就是对一部分内容指定编译的条件,这就是“条件编译”。有时,希望当满足某条件时对一 组语句进行编译,而当条件不满足时则编译另一组语句。 2) 条件编译命令最常见的形式为: \#ifdef 标识符 阅读全文
posted @ 2021-07-20 00:29 超人不会灰啊 阅读(411) 评论(0) 推荐(0)
132、 静态成员与普通成员的区别是什么?
摘要:1) 生命周期 静态成员变量从类被加载开始到类被卸载,一直存在; 普通成员变量只有在类创建对象后才开始存在,对象结束,它的生命期结束; 2) 共享方式 静态成员变量是全类共享;普通成员变量是每个对象单独享用的; 3) 定义位置 普通成员变量存储在栈或堆中,而静态成员变量存储在静态全局区; 4) 初始 阅读全文
posted @ 2021-07-20 00:22 超人不会灰啊 阅读(407) 评论(0) 推荐(1)
131、全局变量和static变量的区别
摘要:1、全局变量(外部变量)的说明之前再冠以static就构成了静态的全局变量。 全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。这两者的区别在于非静态全局变量的作用域是整个源程序,当一个源程 序由多个原文件组成时,非静态的全局变量在各个源文件中都是有效的。 阅读全文
posted @ 2021-07-20 00:00 超人不会灰啊 阅读(753) 评论(0) 推荐(0)
130、定义和声明的区别
摘要:如果是指变量的声明和定义 从编译原理上来说,声明是仅仅告诉编译器,有个某类型的变量会被使用,但是编译器并不会为它分配 任何内存。而定义就是分配了内存。 如果是指函数的声明和定义 声明:一般在头文件里,对编译器说:这里我有一个函数叫function() 让编译器知道这个函数的存在。 定义:一般在源文件 阅读全文
posted @ 2021-07-19 01:08 超人不会灰啊 阅读(207) 评论(0) 推荐(0)
128、你知道重载运算符吗?
摘要:1、 我们只能重载已有的运算符,而无权发明新的运算符;对于一个重载的运算符,其优先级和结合律与内置类型一致才可以;不能改变运算符操作数个数; 2、 两种重载方式:成员运算符和非成员运算符,成员运算符比非成员运算符少一个参数;下标运算符、箭头运算符必须是成员运算符; 3、 引入运算符重载,是为了实现类 阅读全文
posted @ 2021-07-19 01:06 超人不会灰啊 阅读(83) 评论(0) 推荐(0)
127、cout和printf有什么区别?
摘要:cout<<是一个函数,cout<<后可以跟不同的类型是因为cout<<已存在针对各种类型数据的重载,所以 会自动识别数据的类型。输出过程会首先将输出字符放入缓冲区,然后输出到屏幕。 cout是有缓冲输出 flush立即强迫缓冲输出。 printf是无缓冲输出。有输出时立即输出 阅读全文
posted @ 2021-07-19 00:59 超人不会灰啊 阅读(380) 评论(0) 推荐(0)
126、C++中类成员的访问权限和继承权限问题
摘要:1) 三种访问权限 ① public:用该关键字修饰的成员表示公有成员,该成员不仅可以在类内可以被访问,在类外也是可 以被访问的,是类对外提供的可访问接口; ② private:用该关键字修饰的成员表示私有成员,该成员仅在类内可以被访问,在类体外是隐藏状态; ③ protected:用该关键字修饰的 阅读全文
posted @ 2021-07-19 00:57 超人不会灰啊 阅读(327) 评论(0) 推荐(0)
125、为什么模板类一般都是放在一个h文件中
摘要:1) 模板定义很特殊。由template<…>处理的任何东西都意味着编译器在当时不为它分配存储空间,它一直处于等待状态直到被一个模板实例告知。在编译器和连接器的某一处,有一机制能去掉指定模板的多重定义。所以为了容易使用,几乎总是在头文件中放置全部的模板声明和定义。 2) 在分离式编译的环境下,编译器 阅读全文
posted @ 2021-07-19 00:22 超人不会灰啊 阅读(365) 评论(0) 推荐(0)
124、模板类和模板函数的区别是什么?
摘要:函数模板的实例化是由编译程序在处理函数调用时自动完成的,而类模板的实例化必须由程序员在程序 中显式地指定。即函数模板允许隐式调用和显式调用而类模板只能显示调用。在使用时类模板必须加, 而函数模板不必 阅读全文
posted @ 2021-07-19 00:16 超人不会灰啊 阅读(191) 评论(0) 推荐(0)
123、将字符串“hello world”从开始到打印到屏幕上的全过程?
摘要:1.用户告诉操作系统执行HelloWorld程序(通过键盘输入等) 2.操作系统:找到helloworld程序的相关信息,检查其类型是否是可执行文件;并通过程序首部信息,确定代码和数据在可执行文件中的位置并计算出对应的磁盘块地址。 3.操作系统:创建一个新进程,将HelloWorld可执行文件映射到 阅读全文
posted @ 2021-07-19 00:08 超人不会灰啊 阅读(532) 评论(0) 推荐(0)
122、说一说你了解的关于lambda函数的全部知识
摘要:1) 利用lambda表达式可以编写内嵌的匿名函数,用以替换独立函数或者函数对象; 2) 每当你定义一个lambda表达式后,编译器会自动生成一个匿名类(这个类当然重载了()运算符),我 们称为闭包类型(closure type)。那么在运行时,这个lambda表达式就会返回一个匿名的闭包实例, 其 阅读全文
posted @ 2021-07-18 01:43 超人不会灰啊 阅读(191) 评论(0) 推荐(0)
121、你知道printf函数的实现原理是什么吗?
摘要:在C/C++中,对函数参数的扫描是从后向前的。 C/C++的函数参数是通过压入堆栈的方式来给函数传参数的(堆栈是一种先进后出的数据结构),最先 压入的参数最后出来,在计算机的内存中,数据有2块,一块是堆,一块是栈(函数参数及局部变量在 这里),而栈是从内存的高地址向低地址生长的,控制生长的就是堆栈指 阅读全文
posted @ 2021-07-18 01:31 超人不会灰啊 阅读(382) 评论(0) 推荐(0)
120、define、const、typedef、inline的使用方法?他们之间有什么区别?
摘要:一、const与#define的区别: 1) const定义的常量是变量带类型,而#define定义的只是个常数不带类型; 2) define只在预处理阶段起作用,简单的文本替换,而const在编译、链接过程中起作用; 3) define只是简单的字符串替换没有类型检查。而const是有数据类型的, 阅读全文
posted @ 2021-07-18 01:29 超人不会灰啊 阅读(240) 评论(0) 推荐(0)
119、 函数调用过程栈的变化,返回值和参数变量哪个先入栈?
摘要:1、调用者函数把被调函数所需要的参数按照与被调函数的形参顺序相反的顺序压入栈中,即:从右向左依次把被调函数所需要的参数压入栈; 2、调用者函数使用call指令调用被调函数,并把call指令的下一条指令的地址当成返回地址压入栈中(这个压栈操作隐含在call指令中); 3、在被调函数中,被调函数会先保存 阅读全文
posted @ 2021-07-18 01:25 超人不会灰啊 阅读(840) 评论(0) 推荐(1)
118、 结构体变量比较是否相等
摘要:1) 重载了 “==” 操作符 2) 元素的话,一个个比; 3) 指针直接比较,如果保存的是同一个实例地址,则(p1==p2)为真; 阅读全文
posted @ 2021-07-18 01:21 超人不会灰啊 阅读(246) 评论(0) 推荐(0)
117、说一说你理解的内存对齐以及原因
摘要:1、 分配内存的顺序是按照声明的顺序。 2、 每个变量相对于起始位置的偏移量必须是该变量类型大小的整数倍,不是整数倍就空出内存,直到偏移量是整数倍为止。 3、 最后整个结构体的大小必须是里面变量类型最大值的整数倍。 添加了#pragma pack(n)后规则就变成了下面这样: 1、 偏移量要是n和当 阅读全文
posted @ 2021-07-18 01:01 超人不会灰啊 阅读(157) 评论(0) 推荐(0)
116、手写实现智能指针类
摘要:1) 智能指针是一个数据类型,一般用模板实现,模拟指针行为的同时还提供自动垃圾回收机制。它会自动记录SmartPointer<t*>对象的引用计数,一旦T类型对象的引用计数为0,就释放该对象。 除了指针对象外,我们还需要一个引用计数的指针设定对象的值,并将引用计数计为1,需要一个构造函数。新增对象还 阅读全文
posted @ 2021-07-18 00:55 超人不会灰啊 阅读(225) 评论(0) 推荐(0)
115、使用智能指针管理内存资源,RAII是怎么回事?
摘要:1) RAII全称是“Resource Acquisition is Initialization”,直译过来是“资源获取即初始化”,也就是说在构 造函数中申请分配资源,在析构函数中释放资源。 因为C++的语言机制保证了,当一个对象创建的时候,自动调用构造函数,当对象超出作用域的时候会 自动调用析构 阅读全文
posted @ 2021-07-18 00:46 超人不会灰啊 阅读(130) 评论(0) 推荐(0)
114、 内存泄漏的后果?如何监测?解决方法?
摘要:1) 内存泄漏 内存泄漏是指由于疏忽或错误造成了程序未能释放掉不再使用的内存的情况。内存泄漏并非指内存在物 理上消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制; 2) 后果 只发生一次小的内存泄漏可能不被注意,但泄漏大量内存的程序将会出现各种证照:性能下降到内存逐渐用完,导致 阅读全文
posted @ 2021-07-18 00:39 超人不会灰啊 阅读(316) 评论(0) 推荐(0)
113、函数指针?
摘要:1) 什么是函数指针? 函数指针指向的是特殊的数据类型,函数的类型是由其返回的数据类型和其参数列表共同决定的,而函 数的名称则不是其类型的一部分。 一个具体函数的名字,如果后面不跟调用符号(即括号),则该名字就是该函数的指针(注意:大部分情况 下,可以这么认为,但这种说法并不很严格)。 2) 函数指 阅读全文
posted @ 2021-07-18 00:23 超人不会灰啊 阅读(71) 评论(0) 推荐(0)
112、知道C++中的组合吗?它与继承相比有什么优缺点吗?
摘要:一:继承 继承是Is a 的关系,比如说Student继承Person,则说明Student is a Person。继承的优点是子类可以重 写父类的方法来方便地实现对父类的扩展。 继承的缺点有以下几点: ①:父类的内部细节对子类是可见的。 ②:子类从父类继承的方法在编译时就确定下来了,所以无法在运 阅读全文
posted @ 2021-07-17 17:42 超人不会灰啊 阅读(334) 评论(0) 推荐(0)
111、 继承机制中对象之间如何转换?指针和引用之间如何转换?
摘要:1) 向上类型转换 将派生类指针或引用转换为基类的指针或引用被称为向上类型转换,向上类型转换会自动进行,而且向 上类型转换是安全的。 2) 向下类型转换 将基类指针或引用转换为派生类指针或引用被称为向下类型转换,向下类型转换不会自动进行,因为一 个基类对应几个派生类,所以向下类型转换时不知道对应哪个 阅读全文
posted @ 2021-07-17 17:31 超人不会灰啊 阅读(219) 评论(0) 推荐(0)
110、抽象基类为什么不能创建对象?
摘要:抽象类是一种特殊的类,它是为了抽象和设计的目的为建立的,它处于继承层次结构的较上层。 (1)抽象类的定义:称带有纯虚函数的类为抽象类。 (2)抽象类的作用:抽象类的主要作用是将有关的操作作为结果接口组织在一个继承层次结构中,由它来为派生类提供一 个公共的根,派生类将具体实现在其基类中作为接口的操作。 阅读全文
posted @ 2021-07-13 00:17 超人不会灰啊 阅读(773) 评论(0) 推荐(0)
109、什么情况会自动生成默认构造函数?
摘要:1) 带有默认构造函数的类成员对象,如果一个类没有任何构造函数,但它含有一个成员对象,而后者有 默认构造函数,那么编译器就为该类合成出一个默认构造函数。 不过这个合成操作只有在构造函数真正被需要的时候才会发生; 如果一个类A含有多个成员类对象的话,那么类A的每一个构造函数必须调用每一个成员对象的默认 阅读全文
posted @ 2021-07-13 00:14 超人不会灰啊 阅读(353) 评论(0) 推荐(0)
108、如果想将某个类用作基类,为什么该类必须定义而非声明?
摘要:派生类中包含并且可以使用它从基类继承而来的成员,为了使用这些成员,派生类必须知道他们是什么。 阅读全文
posted @ 2021-07-12 23:57 超人不会灰啊 阅读(210) 评论(0) 推荐(0)
107、类如何实现只能静态分配和只能动态分配
摘要:1) 前者是把new、delete运算符重载为private属性。后者是把构造、析构函数设为protected属性,再用子类来动态创建 2) 建立类的对象有两种方式: ① 静态建立,静态建立一个类对象,就是由编译器为对象在栈空间中分配内存; ② 动态建立,A *p = new A();动态建立一个类 阅读全文
posted @ 2021-07-12 23:52 超人不会灰啊 阅读(536) 评论(0) 推荐(1)
106、C++中的指针参数传递和引用参数传递有什么区别?底层原理你知道吗?
摘要:1) 指针参数传递本质上是值传递,它所传递的是一个地址值。 值传递过程中,被调函数的形式参数作为被调函数的局部变量处理,会在栈中开辟内存空间以存放由主 调函数传递进来的实参值,从而形成了实参的一个副本(替身)。 值传递的特点是,被调函数对形式参数的任何操作都是作为局部变量进行的,不会影响主调函数的实 阅读全文
posted @ 2021-07-12 23:23 超人不会灰啊 阅读(574) 评论(0) 推荐(0)
104、 怎样判断两个浮点数是否相等?
摘要:对两个浮点数判断大小和是否相等不能直接用==来判断,会出错!明明相等的两个数比较反而是不相 等!对于两个浮点数比较只能通过相减并与预先设定的精度比较,记得要取绝对值!浮点数与0的比较 也应该注意。与浮点数的表示方式有关。 阅读全文
posted @ 2021-07-12 23:07 超人不会灰啊 阅读(285) 评论(0) 推荐(0)
103、指针加减计算要注意什么?
摘要:指针加减本质是对其所指地址的移动,移动的步长跟指针的类型是有关系的,因此在涉及到指针加减运 算需要十分小心,加多或者减多都会导致指针指向一块未知的内存地址,如果再进行操作就会很危险。 阅读全文
posted @ 2021-07-12 23:01 超人不会灰啊 阅读(92) 评论(0) 推荐(0)
102、全局变量和局部变量有什么区别?
摘要:生命周期不同:全局变量随主程序创建和创建,随主程序销毁而销毁;局部变量在局部函数内部,甚至 局部循环体等内部存在,退出就不存在; 使用方式不同:通过声明后全局变量在程序的各个部分都可以用到;局部变量分配在堆栈区,只能在局部使用。 操作系统和编译器通过内存分配的位置可以区分两者,全局变量分配在全局数据 阅读全文
posted @ 2021-07-12 22:48 超人不会灰啊 阅读(519) 评论(0) 推荐(0)
101、引用是否能实现动态绑定,为什么可以实现?
摘要:可以。 引用在创建的时候必须初始化,在访问虚函数时,编译器会根据其所绑定的对象类型决定要调用哪个函数。注意只能调用虚函数。 #include <iostream>using namespace std;class Base{public: virtual void fun() { cout << " 阅读全文
posted @ 2021-07-12 22:47 超人不会灰啊 阅读(451) 评论(0) 推荐(0)
100、C++ 11有哪些新特性?
摘要:1.nullptr替代 NULL 2.引入了 auto 和 decltype 这两个关键字实现了类型推导 3.基于范围的 for 循环for(auto& i : res){} 4.类和结构体的中初始化列表 5.Lambda 表达式(匿名函数) 6.std::forward_list(单向链表) 7. 阅读全文
posted @ 2021-07-11 01:28 超人不会灰啊 阅读(78) 评论(0) 推荐(0)
99、静态类型和动态类型,静态绑定和动态绑定的介绍
摘要:1.静态类型:对象在声明时采用的类型,在编译期既已确定; 2.动态类型:通常是指一个指针或引用目前所指对象的类型,是在运行期决定的; 3.静态绑定:绑定的是静态类型,所对应的函数或属性依赖于对象的静态类型,发生在编译期; 4.动态绑定:绑定的是动态类型,所对应的函数或属性依赖于对象的动态类型,发生在 阅读全文
posted @ 2021-07-11 01:23 超人不会灰啊 阅读(401) 评论(0) 推荐(0)
97、什么是虚拟继承
摘要:由于C++支持多继承,除了public、protected和private三种继承方式外,还支持虚拟(virtual)继承, 举个例子: #include <iostream>using namespace std;class A{}class B : virtual public A{};clas 阅读全文
posted @ 2021-07-11 00:44 超人不会灰啊 阅读(245) 评论(0) 推荐(0)
93、拷贝构造函数和赋值运算符重载的区别?
摘要:1.拷贝构造函数是函数,赋值运算符是运算符重载。 2.拷贝构造函数会生成新的类对象,赋值运算符不能。 3.拷贝构造函数是直接构造一个新的类对象,所以在初始化对象前不需要检查源对象和新建对象是否 相同;赋值运算符需要上述操作并提供两套不同的复制策略,另外赋值运算符中如果原来的对象有 内存分配则需要先把 阅读全文
posted @ 2021-07-10 21:49 超人不会灰啊 阅读(314) 评论(0) 推荐(0)
92、构造函数、拷贝构造函数和赋值操作符的区别
摘要:构造函数: 对象不存在,没用别的对象初始化,在创建一个新的对象时调用构造函数 拷贝构造函数: 对象不存在,但是使用别的已经存在的对象来进行初始化 赋值运算符: 对象存在,用别的对象给它赋值,这属于重载“=”号运算符的范畴,“=”号两侧的对象都是已存在的 举个例子: #include <iostrea 阅读全文
posted @ 2021-07-10 21:45 超人不会灰啊 阅读(125) 评论(0) 推荐(0)
90、关于this指针你知道什么?全说出来
摘要:1.this指针是类的指针,指向对象的首地址。 2.this指针只能在成员函数中使用,在全局函数、静态成员函数中都不能用this。 3.this指针只有在成员函数中才有定义,且存储位置会因编译器不同有不同存储位置。 this指针的用处 一个对象的this指针并不是对象本身的一部分,不会影响sizeo 阅读全文
posted @ 2021-07-10 21:25 超人不会灰啊 阅读(315) 评论(0) 推荐(0)
89、C++中将临时变量作为返回值时的处理过程
摘要:首先需要明白一件事情,临时变量,在函数调用过程中是被压到程序进程的栈中的,当函数退出时,临 时变量出栈,即临时变量已经被销毁,临时变量占用的内存空间没有被清空,但是可以被分配给其他变 量,所以有可能在函数退出时,该内存已经被修改了,对于临时变量来说已经是没有意义的值了 C语言里规定:16bit程序中 阅读全文
posted @ 2021-07-10 21:08 超人不会灰啊 阅读(498) 评论(0) 推荐(0)
87、C++函数调用的压栈过程
摘要:#include <iostream>using namespace std;int f(int n){ cout << n << endl; return n;}void func(int param1, int param2){ int var1 = param1; int var2 = par 阅读全文
posted @ 2021-07-10 21:04 超人不会灰啊 阅读(650) 评论(0) 推荐(0)
82、类什么时候会析构?
摘要:1) 对象生命周期结束,被销毁时; 2) delete指向对象的指针时,或delete指向对象的基类类型指针,而其基类虚构函数是虚函数时; 3) 对象i是对象o的成员,o的析构函数被调用时,对象i的析构函数也被调用。 阅读全文
posted @ 2021-07-10 20:28 超人不会灰啊 阅读(181) 评论(0) 推荐(0)
84、智能指针的原理、常用的智能指针及实现
摘要:原理 智能指针是一个类,用来存储指向动态分配对象的指针,负责自动释放动态分配的对象,防止堆内存泄漏。动态分配的资源,交给一个类对象去管理,当类对象声明周期结束时,自动调用析构函数释放资源 常用的智能指针 (1) shared_ptr 实现原理:采用引用计数器的方法,允许多个智能指针指向同一个对象,每 阅读全文
posted @ 2021-07-10 12:19 超人不会灰啊 阅读(375) 评论(0) 推荐(0)
81、构造函数一般不定义为虚函数的原因
摘要:(1)创建一个对象时需要确定对象的类型,而虚函数是在运行时动态确定其类型的。在构造一个对象时,由于对象还未创建成功,编译器无法知道对象的实际类型 (2)虚函数的调用需要虚函数表指针vptr,而该指针存放在对象的内存空间中,若构造函数声明为虚 函数,那么由于对象还未创建,还没有内存空间,更没有虚函数表 阅读全文
posted @ 2021-07-10 12:18 超人不会灰啊 阅读(220) 评论(0) 推荐(0)
80、构造函数析构函数可否抛出异常
摘要:1) C++只会析构已经完成的对象,对象只有在其构造函数执行完毕才算是完全构造妥当。在构造函数中发生异常,控制权转出构造函数之外。 因此,在对象b的构造函数中发生异常,对象b的析构函数不会被调用。因此会造成内存泄漏。 2) 用auto_ptr对象来取代指针类成员,便对构造函数做了强化,免除了抛出异常 阅读全文
posted @ 2021-07-10 11:59 超人不会灰啊 阅读(176) 评论(0) 推荐(0)
79、虚析构函数的作用,父类的析构函数是否要设置为虚函数?
摘要:1) C++中基类采用virtual虚析构函数是为了防止内存泄漏。 2) 纯虚析构函数一定得定义,因为每一个派生类析构函数会被编译器加以扩张,以静态调用的方式调用其每一个虚基类以及上一层基类的析构函数。 阅读全文
posted @ 2021-07-09 19:26 超人不会灰啊 阅读(129) 评论(0) 推荐(0)
78、构造函数、析构函数的执行顺序?
摘要:1) 构造函数顺序 ① 基类构造函数。如果有多个基类,则构造函数的调用顺序是某类在类派生表中出现的顺序,而不是 它们在成员初始化表中的顺序。 ② 成员类对象构造函数。如果有多个成员类对象则构造函数的调用顺序是对象在类中被声明的顺序, 而不是它们出现在成员初始化表中的顺序。 ③ 派生类构造函数。 2) 阅读全文
posted @ 2021-07-09 19:20 超人不会灰啊 阅读(352) 评论(0) 推荐(0)
77、构造函数和析构函数可以调用虚函数吗,为什么
摘要:1) 在C++中,提倡不在构造函数和析构函数中调用虚函数; 2) 构造函数和析构函数调用虚函数时都不使用动态联编,如果在构造函数或析构函数中调用虚函数,则 运行的是为构造函数或析构函数自身类型定义的版本; 3) 因为父类对象会在子类之前进行构造,此时子类部分的数据成员还未初始化,因此调用子类的虚函数 阅读全文
posted @ 2021-07-09 19:16 超人不会灰啊 阅读(327) 评论(0) 推荐(0)
75、(超重要)构造函数为什么不能为虚函数?析构函数为什么要虚函数?
摘要:1、 从存储空间角度,虚函数相应一个指向vtable虚函数表的指针,这大家都知道,但是这个指向 vtable 的指针事实上是存储在对象的内存空间的。 问题出来了,假设构造函数是虚的,就须要通过 vtable来调用,但是对象还没有实例化,也就是内存空 间还没有,怎么找vtable呢?所以构造函数不能是 阅读全文
posted @ 2021-07-07 14:20 超人不会灰啊 阅读(349) 评论(0) 推荐(0)
74、成员初始化列表的概念,为什么用它会快一些?
摘要:成员初始化列表的概念 在类的构造函数中,不在函数体内对成员变量赋值,而是在构造函数的花括号前面使用冒号和初始化列表赋值 效率 用初始化列表会快一些的原因是,对于类型,它少了一次调用构造函数的过程,而在函数体中赋值则会 多一次调用。而对于内置数据类型则没有差别。 阅读全文
posted @ 2021-07-07 00:33 超人不会灰啊 阅读(307) 评论(0) 推荐(0)
73、C++中类的数据成员和成员函数内存分布情况
摘要:一个类对象的地址就是类所包含的这一片内存空间的首地址,这个首地址也就对应具体某一个成员变量 的地址。(在定义类对象的同时这些成员变量也就被定义了) 对象的大小和对象中数据成员的大小是一致的,也就是说,成员函数不占用对象 的内存。这是因为所有的函数都是存放在代码区的,不管是全局函数,还是成员函数。要是 阅读全文
posted @ 2021-07-07 00:28 超人不会灰啊 阅读(223) 评论(0) 推荐(0)
72、介绍面向对象的三大特性,并且举例说明
摘要:三大特性:继承、封装和多态 (1)继承 让某种类型对象获得另一个类型对象的属性和方法。 它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展 常见的继承有三种方式: 1. 实现继承:指使用基类的属性和方法而无需额外编码的能力 2. 接口继承:指仅使用属性和方法的名称、但是子 阅读全文
posted @ 2021-07-06 21:42 超人不会灰啊 阅读(479) 评论(0) 推荐(0)
69、什么是内存泄露,如何检测与避免
摘要:内存泄露 一般我们常说的内存泄漏是指堆内存的泄漏。堆内存是指程序从堆中分配的,大小任意的(内存块的大小 可以在程序运行期决定)内存块,使用完后必须显式释放的内存。应用程序般使用malloc,、realloc、 new等函数从堆中分配到块内存,使用完后,程序必须负责相应的调用free或delete释放 阅读全文
posted @ 2021-07-06 21:31 超人不会灰啊 阅读(463) 评论(0) 推荐(0)
68、成员列表初始化?
摘要:1) 必须使用成员初始化的四种情况 ① 当初始化一个引用成员时; ② 当初始化一个常量成员时; ③ 当调用一个基类的构造函数,而它拥有一组参数时; ④ 当调用一个成员类的构造函数,而它拥有一组参数时; 2) 成员初始化列表做了什么 ① 编译器会一一操作初始化列表,以适当的顺序在构造函数之内安插初始化 阅读全文
posted @ 2021-07-06 21:28 超人不会灰啊 阅读(94) 评论(0) 推荐(0)
67、类成员初始化方式?构造函数的执行顺序 ?为什么用成员初始化列表会快一 些?
摘要:1) 赋值初始化,通过在函数体内进行赋值初始化;列表初始化,在冒号后使用初始化列表进行初始化。 这两种方式的主要区别在于: 1.对于在函数体中初始化,是在所有的数据成员被分配内存空间后才进行的。 2.列表初始化是给数据成员分配内存空间时就进行初始化,就是说分配一个数据成员只要冒号后有此数据成 员的赋 阅读全文
posted @ 2021-07-06 21:13 超人不会灰啊 阅读(202) 评论(0) 推荐(0)
64、malloc申请的存储空间能用delete释放吗?
摘要:不能,malloc /free主要为了兼容C,new和delete 完全可以取代malloc /free的。 malloc /free的操作对象都是必须明确大小的,而且不能用在动态类上。 new 和delete会自动进行类型检查和大小,malloc/free不能执行构造函数与析构函数,所以动态对象它 阅读全文
posted @ 2021-07-05 00:49 超人不会灰啊 阅读(1519) 评论(0) 推荐(0)
63、new和delete的实现原理, delete是如何知道释放内存的大小的额?
摘要:1、 new简单类型直接调用operator new分配内存; 而对于复杂结构,先调用operator new分配内存,然后在分配的内存上调用构造函数; 对于简单类型,new[]计算好大小后调用operator new; 对于复杂数据结构,new[]先调用operator new[]分配内存,然后在 阅读全文
posted @ 2021-07-05 00:47 超人不会灰啊 阅读(510) 评论(0) 推荐(0)
62、delete p、delete [] p、allocator都有什么作用?
摘要:1、 动态数组管理new一个数组时,[]中必须是一个整数,但是不一定是常量整数,普通数组必须是一 个常量整数; 2、 new动态数组返回的并不是数组类型,而是一个元素类型的指针; 3、 delete[]时,数组中的元素按逆序的顺序进行销毁; 4、 new在内存分配上面有一些局限性,new的机制是将内 阅读全文
posted @ 2021-07-04 10:31 超人不会灰啊 阅读(297) 评论(0) 推荐(0)
60、C++模板是什么,你知道底层怎么实现的?
摘要:1) 编译器并不是把函数模板处理成能够处理任意类的函数;编译器从函数模板通过具体类型产生不同 的函数;编译器会对函数模板进行两次编译:在声明的地方对模板代码本身进行编译,在调用的地方对 参数替换后的代码进行编译。 2) 这是因为函数模板要被实例化后才能成为真正的函数,在使用函数模板的源文件中包含函数 阅读全文
posted @ 2021-07-04 09:52 超人不会灰啊 阅读(624) 评论(0) 推荐(1)
59、深拷贝与浅拷贝是怎么回事?
摘要:1) 浅复制 :只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种拷贝 叫做“(浅复制)浅拷贝”,换句话说,浅复制仅仅是指向被复制的内存地址,如果原地址中对象被改变 了,那么浅复制出来的对象也会相应改变。 深复制 :在计算机中开辟了一块新的内存地址用于存放复制的对象。 2) 阅读全文
posted @ 2021-07-04 01:47 超人不会灰啊 阅读(115) 评论(0) 推荐(0)
56、什么是类的继承?
摘要:1) 类与类之间的关系 has-A包含关系,用以描述一个类由多个部件类构成,实现has-A关系用类的成员属性表示,即一个类的 成员属性是另一个已经定义好的类; use-A,一个类使用另一个类,通过类之间的成员函数相互联系,定义友元或者通过传递参数的方式来实现; is-A,继承关系,关系具有传递性; 阅读全文
posted @ 2021-07-04 01:46 超人不会灰啊 阅读(488) 评论(0) 推荐(0)
55、值传递、指针传递、引用传递的区别和效率
摘要:1) 值传递:有一个形参向函数所属的栈拷贝数据的过程,如果值传递的对象是类对象 或是大的结构 体对象,将耗费一定的时间和空间。(传值) 2) 指针传递:同样有一个形参向函数所属的栈拷贝数据的过程,但拷贝的数据是一个固定为4字节的地 址。(传值,传递的是地址值) 3) 引用传递:同样有上述的数据拷贝过 阅读全文
posted @ 2021-07-03 23:28 超人不会灰啊 阅读(531) 评论(0) 推荐(0)
54、形参与实参的区别?
摘要:1) 形参变量只有在被调用时才分配内存单元,在调用结束时, 即刻释放所分配的内存单元。因此,形 参只有在函数内部有效。 函数调用结束返回主调函数后则不能再使用该形参变量。 2) 实参可以是常量、变量、表达式、函数等, 无论实参是何种类型的量,在进行函数调用时,它们都 必须具有确定的值, 以便把这些值 阅读全文
posted @ 2021-07-03 23:26 超人不会灰啊 阅读(359) 评论(0) 推荐(0)
53、指针和const的用法
摘要:1) 当const修饰指针时,由于const的位置不同,它的修饰对象会有所不同。 2) int *const p2中const修饰p2的值,所以理解为p2的值不可以改变,即p2只能指向固定的一个变量地 址,但可以通过*p2读写这个变量的值。顶层指针表示指针本身是一个常量 3) int const * 阅读全文
posted @ 2021-07-03 23:23 超人不会灰啊 阅读(151) 评论(0) 推荐(0)
52、const关键字?
摘要:1) 阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进行初始化, 因为以后就没有机会再去改变它了; 2) 对指针来说,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指定为 const; 3) 在一个函数声明中,const可以修饰形 阅读全文
posted @ 2021-07-03 23:21 超人不会灰啊 阅读(87) 评论(0) 推荐(0)
50、static的用法和作用?
摘要:1.先来介绍它的第一条也是最重要的一条:隐藏。(static函数,static变量均可) 当同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性。 2.static的第二个作用是保持变量内容的持久。 (static变量中的记忆功能和全局生存期)存储在静态数 据区的变量会在程序 阅读全文
posted @ 2021-07-03 16:33 超人不会灰啊 阅读(873) 评论(0) 推荐(0)
49、C++的异常处理的方法
摘要:在程序执行过程中,由于程序员的疏忽或是系统资源紧张等因素都有可能导致异常,任何程序都无法保 证绝对的稳定,常见的异常有: 1.数组下标越界 2.除法计算时除数为0 3.动态分配空间时空间不足 (1)try、throw和catch关键字 #include <iostream>using namespa 阅读全文
posted @ 2021-07-03 16:15 超人不会灰啊 阅读(233) 评论(0) 推荐(0)
48、简要说明C++的内存分区
摘要:C++中的内存分区,分别是堆、栈、自由存储区、全局/静态存储区、常量存储区和代码区。 栈:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动 被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限 堆:就是那些由 new 分配的内存块,他们 阅读全文
posted @ 2021-07-02 22:01 超人不会灰啊 阅读(191) 评论(0) 推荐(0)
47、C++中NULL和nullptr区别
摘要:算是为了与C语言进行兼容而定义的一个问题吧 NULL来自C语言,一般由宏定义实现,而 nullptr 则是C++11的新增关键字。 在C语言中,NULL被定义 为(void*)0, 而在C++语言中,NULL则被定义为整数0。 阅读全文
posted @ 2021-07-01 00:43 超人不会灰啊 阅读(149) 评论(0) 推荐(0)