C/C++
nguliu
这个作者很懒,什么都没留下…
展开
-
C++虚继承和虚基类详解
1.多继承与菱形继承多继承(Multiple Inheritance)是指从多个直接基类中产生派生类的能力,多继承的派生类继承了所有父类的成员。尽管概念上非常简单,但是多个基类的相互交织可能会带来错综复杂的设计问题,命名冲突就是不可回避的一个。多继承时很容易产生命名冲突,即使我们很小心地将所有类中的成员变量和成员函数都命名为不同的名字,命名冲突依然有可能发生,比如典型的是菱形继承,如下图所示:...原创 2020-02-04 23:53:37 · 473 阅读 · 0 评论 -
成员函数的重载、覆盖与隐藏
成员函数的重载、覆盖(override)与隐藏很容易混淆,C++程序员必须要搞清楚概念,否则错误将防不胜防。重载与覆盖成员函数被重载的特征:相同的范围(在同一个类中)函数名字相同参数不同(参数类型或参数个数)virtual 关键字可有可无const属性也可构成重载,返回值不能构成重载覆盖是指派生类函数覆盖基类的virtual函数,特征是:不同的范围(分别位于派生类与基类)...转载 2019-12-17 15:23:38 · 233 阅读 · 0 评论 -
C++ 内存对齐原则及作用
struct/class/union内存对齐原则有四个:数据成员对齐规则:结构(struct/class)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int在32位机为4字节, 则要从4的整数倍地址开始存储),基本类型不包括struct/class/unio...转载 2019-12-15 12:27:23 · 1553 阅读 · 0 评论 -
C++hash_map实现
hash_map除了不具备map自动排序的功能以外,具有map所有的特性。hash_map使用hashtable作为底层容器,hashtable提供了所有hash_map需要的操作,hash_map不允许键值重复,使用hashtable的insert_unique来插入元素代码实现:https://github.com/inmail/mySTL/blob/master/mySTL/19stl_h...原创 2019-10-17 10:43:09 · 309 阅读 · 0 评论 -
C++hash_set实现
运用set,为的是能够快速搜寻元素,这一点不论是rb-tree和hashtable都能够达到目的,但前者有自动排序功能而hashtable没有。hash_set使用hashtable作为底层容器,hashtable提供了所有hash_set需要的操作,hash_set不允许键值重复,使用hashtable的insert_unique来插入元素代码实现:https://github.com/inm...原创 2019-10-17 10:42:00 · 1065 阅读 · 0 评论 -
C++hashtable实现
二叉搜索树具有对数平均时间的表现,但这样的表现是构造在一个假设上的:输入的数据具有足够的随机性,对于hashtable,它在插入、删除、搜寻等操作上也具有“常数平均时间”的表现,而且这种次表现是以统计为基础,不需要依赖数据输入的随机性。hashtable可提供对任何有名项的存取操作和删除操作,所以hashtable也可以被看做一种字典结构。相较于rb-tree,当hashtable负载因子过大时,...原创 2019-10-17 10:40:46 · 415 阅读 · 0 评论 -
C++map的实现
map的特性是:所有元素都会根据元素的键值被自动排序,map的所有元素都是pair,同时拥有实值(value)和键值(key),pair的第一元素被视为键值,第二元素被视为实值,通常通过仿函数select提取出节点的键值进行比较,我们能修改节点的实值但不能修改其键值,对其他元素操作时,其之前和之后的迭代器也都不回失效。map使用rb-tree作为底层容器,rb-tree提供了所有map需要的操作,...原创 2019-10-17 10:39:18 · 2973 阅读 · 0 评论 -
C++set的实现
set提供快速的查找功能,其特性是:所有元素都会根据元素的键值自动排序,对set执行添加或删除操作时,操作之前的所有迭代器和操作之后的所有迭代器都依然有效。set使用rb-tree作为底层容器,rb-tree提供了所有set需要的操作,set不允许键值重复,使用rb-tree的insert_unique来插入元素代码实现:https://github.com/inmail/mySTL/blob/...原创 2019-10-17 10:37:02 · 1911 阅读 · 0 评论 -
C++红黑树实现
红黑树是一种运用及广的自平衡二叉搜索树,可提供对数时间的插入和访问操作,其平衡性不如AVL树高,因此其维护平衡性的成本也不如AVL树高,相当于在平衡性和效率之间取了折中。这里主要实现了红黑树的数据结构、旋转算法、插入算法、删除算法等,其中删除算法是最难但又必须使用的,对于删除过程不了解的同学请查看https://blog.csdn.net/qq_40843865/article/details/1...原创 2019-10-17 10:34:22 · 223 阅读 · 0 评论 -
C++ slist实现
slist和list最大的区别在于,前者的迭代器属于单向的ForwardIterator,而后者是双向迭代器BidirectionalIterator。因此slist的功能就受到很多限制,但slist消耗的空间更少。和list一样,它们的插入、移除、接合等操作不会造成原有的迭代器失效。注意:根据STL的习惯,插入操作会将元素插入到迭代器所指位置之前而不是之后,但slist没办法快速找到其前一个节...原创 2019-10-08 16:24:47 · 1402 阅读 · 0 评论 -
C++ priority_queue实现
优先级队列的实现,这是一个配接器而不是一个容器,它默认以vector为底层容器,通过heap调用相关算法,维持底层容器中的元素保持堆的特性代码实现:https://github.com/inmail/mySTL/blob/master/mySTL/9stl_priority_queue.h...原创 2019-10-08 14:49:28 · 558 阅读 · 0 评论 -
C++二叉堆实现
heap并不属于标准库的内容,这里主要提供push_heap、pop_head、sort_heap、make_heap几个泛型算法,它们接受一对迭代器和一个权值比较规则,对底层容器中迭代器范围内的元素进行相应操作,从而维持底层容器堆的特性代码实现:https://github.com/inmail/mySTL/blob/master/mySTL/9stl_heap.h...原创 2019-10-08 14:47:48 · 252 阅读 · 0 评论 -
C++ queue实现
queue是单向队列,它与stack一样,都是一个配接器,其内部使用list作为底层容器(也可使用deque、vector等),它通过底层容器实现对外操作,因而实现非常简单代码实现:https://github.com/inmail/mySTL/blob/master/mySTL/8stl_queue.h...原创 2019-10-06 13:38:49 · 374 阅读 · 0 评论 -
C++ stack实现
stack实际不是一种容器而是一个配接器,其内部使用list作为底层容器(也可使用deque、vector等),它通过底层容器实现对外操作,因而实现非常简单代码实现:https://github.com/inmail/mySTL/blob/master/mySTL/7stl_stack.h...原创 2019-10-06 13:37:22 · 520 阅读 · 0 评论 -
C++ deque实现
deque是序列式容器中设计难度最大的容器,主要原因在于其特殊的数据结构和配套的迭代器设计(从deque的设计中可以看出每种容器只能由自己来设计迭代器)。其内部首先以一块连续的空间作为map,map内的每个node指向一块连续的缓冲区,这些连续的缓冲区才是真正存放数据的位置,初始状态是它维护一个空的缓冲区,当一块缓冲区满时,需要申请一块新的缓冲区,并通过map内的一个node记录其位置,当map...原创 2019-10-05 17:19:53 · 1091 阅读 · 1 评论 -
C++ list实现
list作为一个双向链表对外表现,其内部实际是一个双向循环链表,初始状态时有一个空的节点组成双向循环链表。它的优点是插入、删除、接合等操作时不会使其他迭代器失效(甚至进行操作的那个迭代器也不会失效),由于涉及到大量的指针操作,其涉及难度大于vector。为了能融入STL算法,它必须使用定制的迭代器而不能使用原生的指针。由于STL的sort算法只接受随机迭代器,而list的迭代器是双向迭代器不支持随...原创 2019-10-05 13:35:35 · 1039 阅读 · 0 评论 -
C++ vector实现
vector具有array的有点同时又有许多高效的优化,主要优点有顺序存储、随机访问、动态扩容、预分配等,它的插入操作和删除操作容易导致迭代器的失效,它使用原生指针作为迭代器代码实现:https://github.com/inmail/mySTL/blob/master/mySTL/4stl_vector.h...原创 2019-10-05 13:34:09 · 266 阅读 · 0 评论 -
C++string类实现
C++ string实际是对char* 的封装,它使用原生的指针作为迭代器代码实现:https://github.com/inmail/mySTL/blob/master/mySTL/3stl_string.h原创 2019-10-05 13:32:17 · 120 阅读 · 0 评论 -
C语言清空输入缓冲区
C语言编程 - 清空键盘输入缓冲区 清空键盘缓冲区很多种方法,如用fflush(stdin); rewind(stdin);等,但是在linux这些都不起作用,还得我今天试了半天都没成功,上网搜了一下发现setbuf(stdin, NULL);就能直接清空键盘缓冲区了。以下几个实例:Sample one 1 2 3 4 5 6 7 8...原创 2018-07-16 21:49:26 · 10942 阅读 · 2 评论 -
C语言各数据类型字节数
在C语言中,任何一个变量都占用一段地址,不同类型的变量占用的内存大小不同,同种类型变量在不同编译平台的大小也不同,各类型大小如图:类型 16位 32位 64位 char 1 1 1 short int 2 2 2 int 2 4 4 unsigned int 2 4 4 long in...原创 2018-07-23 21:44:30 · 3447 阅读 · 0 评论 -
C语言指针数组和数组指针辨析
1.指针数组:即指针组成的数组,数组中每一个元素均为一个指针定义:int *p[n];[ ]优先级高,先与p结合成为一个数组,再由int*说明这是一个整型指针数组,它有n个指针类型的数组元素。 int a=1,b=2,c=3; int *p[3] = {&a,&b,&c}; //定义拥有3个元素的指针数组并赋初值为 a,b,c 地址 print...原创 2018-07-25 14:43:27 · 200 阅读 · 0 评论 -
strcpy memcpy strcmp strlen strcat strstr strchr实现及辨析
1.strcpy实现以下是C标准库写法,其最大隐患是有可能 dst 的长度小于 strlen(src) + 1 造成越界访问,或是类似 strcpy(ptr + 1, ptr) 发生重叠造成无限循环。#include <assert.h>char* strcpy(char* dst, const char* src){ assert(dst); assert(src...原创 2019-05-12 10:22:19 · 328 阅读 · 0 评论 -
constexpr关键字的作用
1.constexpr 的作用从代码到程序要经历两个过程:编译 和 链接constexpr 关键字使得代码在编译过程中,如果编译器对于某个表达式已经得到足够多的信息,那么编译器会在编译器一结束就把该表达式的结果求出来。即对于无constexpr 关键字的表达式是在运行期执行,对于有constexpr 关键字的表达式是在编译期执行。2.运用实例#include "pch.h"...原创 2019-04-23 01:23:24 · 3064 阅读 · 0 评论 -
C++中volatile关键字的作用
对于较官方的解释是:volatile作为指令关键字,确保本条指令不会因编译器的优化而被省略,即系统每次从变量所在内存读取数据而不是从寄存器读取备份。下面将进行详细说明:易变性编译器对volatile修饰的变量,当要读取这个变量时,任何情况下都会从内存中读取,而不会从寄存器缓存中读取(因为每次都从内存中读取体现出变量的“易变”)对于非volatile变量对 b = a + 1;这条语句,...转载 2019-06-01 15:18:24 · 4806 阅读 · 0 评论 -
C++中explicit关键字作用
首先, C++中的explicit关键字只能用于修饰只有一个参数的类构造函数, 它的作用是表明该构造函数是显示的, 而非隐式的, 跟它相对应的另一个关键字是implicit, 意思是隐藏的,类构造函数默认情况下即声明为implicit(隐式).那么显示声明的构造函数和隐式声明的有什么区别呢? 我们来看下面的例子:class CxString // 没有使用explicit关键字的类声明...原创 2019-08-09 17:58:02 · 349 阅读 · 0 评论 -
C++中四种类型转换的区别
一、四种转换类型比较:类型转换有c风格的,当然还有c++风格的。c风格的转换的格式很简单 (type)expression,但是c风格的类型转换有不少的缺点,有的时候用c风格的转换是不合适的,因为它可以在任意类型之间转换,比如你可以把一个指向const对象的指针转换成指向非const对象的指针,把一个指向基类对象的指针转换成指向一个派生类对象的指针,这两种转换之间的差别是巨大的,但是传统的c语...转载 2019-08-07 17:25:24 · 930 阅读 · 0 评论 -
C++值语意与对象语意
【1】什么是值语义?所谓值语义是指目标对象由源对象拷贝生成,且生成后与源对象完全无关,彼此独立存在,改变互不影响。就像 int 类型变量相互拷贝一样。C++的内置类型(bool/int/double/char)都是值语义,标准库里的 complex<>、pair<>、vector<>、map<>、string 等等类型也都是值语义。拷贝之...转载 2019-08-07 19:55:41 · 291 阅读 · 0 评论 -
memmove 和 memcpy的区别
函数原型及作用memcpy 和 memmove 都是C语言中的库函数,在头文件string.h中,作用是拷贝一定长度的内存的内容,原型分别如下:void* memcpy(void *dst, const void src, size_t count);void memmove(void *dst, const void *src, size_t count);他们的作用是一样的,唯一的区别...原创 2019-09-30 16:08:34 · 6040 阅读 · 4 评论 -
C++空间配置器实现
对于new运算符内含两个阶段的操作:①调用::operator配置内存,②调用构造函数构造内容,空间配置器主要作用是①配置内存。对于空间配置器主要实现了第一级空间配置器、第二级空间配置器和内存池,其中第一级空间配置器直接使用malloc/free/realloc等函数,第二级空间配置器维护16个8~128byte的自由链表(组织形式类似hash开链)和一个内存池,每次获取/释放内存时都是从自由链...原创 2019-10-05 11:49:47 · 236 阅读 · 0 评论 -
C++对象构造和析构工具的实现
对于new运算符内含两个阶段的操作:①调用::operator配置内存,②调用构造函数构造内容对于delete运算符内含两个阶段操作:③调用析构函数将对象析构,④调用::operator delete函数释放内存构造器/析构器主要作用是②③:内容构造与析构它主要实现了全局函数construct和destroy,construct在已申请的内存空间上构造内容,destroy析构特定内存空间上的...原创 2019-10-05 12:00:02 · 121 阅读 · 0 评论 -
C++迭代器榨汁机iterator_traits实现
通过迭代器榨汁机iterator_traits很容易萃取出迭代器的iterator_category、value_type、difference_type、pointer、reference等特性,distance_type、iterator_category、value_type是对iterator_traits的封装,用于提取常用的迭代器属性代码实现:https://github.com/i...原创 2019-10-05 12:06:26 · 224 阅读 · 0 评论 -
C++ traits编程技法实现
type_traits用于萃取型别的一些特性这里我们所关注的型别特性是指:这个型别是否具备non-trivial constructor?是否具备non-trivial copy constructor?是否具备non-trivial assignment operator?是否具备non-trivial destructor?如果答案是否定的,我们对这个型别进行构造、析构、拷贝、复制等操作时,...原创 2019-10-05 13:26:06 · 206 阅读 · 0 评论 -
C语言指针深度剖析
1.数组元素访问方式1.一维数组访问数组元素的4种方法: 1.下标法,用a[i]来访问数组元素; 2.指针法,(ptr+i)形式间接访问; 3.数组名,用(a+i)形式访问数组; 4.指针下标法,ptr[i]形式访问数组元素; 2.二维数组访问数组元素# 1.直接访问法printf("%d",a[i][j]);# 2.指针访问法int *ptr;ptr=a[0];...原创 2018-06-29 21:59:21 · 421 阅读 · 0 评论