C/C++
C/C++入门到进阶
&动感超人
读书笔记,不求甚解!
展开
-
C++进阶——内存管理(三)
在VC和BorlandC5.0编译器标准库内部实现中,容器的std::allocater都是通过::operator new/delete来完成的,其本质就是直接调用malloc 和 free其他什么都没有做。而GNU2.9 C++中使用的版本是std::alloc——使用了诸如pool等高级的分配逻辑,在经过更新迭代后在GNU4.9中改名为__gnu_cxx::__pool_alloc!GNU2.9中std::alloc的实现考虑到小型内存所可能造成的内存破损问题,SGI设计了双层级配置器,第..原创 2020-09-27 00:44:05 · 372 阅读 · 0 评论 -
C++进阶——内存管理(二)
C++ memory primitives分配 释放 类型 可否重载 malloc free C函数 不可 new delete C++表达式 不可 ::operator new ::operator delete C++函数 可 allocator<T>::allocate allocator<int>::deallocate C++标准库 可自由设计并以之搭配任何容器原创 2020-09-25 00:27:46 · 477 阅读 · 0 评论 -
C++进阶——内存管理(一)
[导语]内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题,C++高手从中获得了更好的性能,更大的自由,C++菜鸟的收获则是一遍一遍的检查代码和对C++的痛恨,但内存管理在C++中无处不在,内存泄漏几乎在每个C++程序中都会发生,因此要想成为C++高手,内存管理一关是必须要过的,除非放弃C++,转到Java或者.NET,他们的内存管理基本是自动的,当然你也放弃了自由和对内存的支配权,还放弃了C++超绝的性能。本期专题将从内存管理、内存泄漏、内存回收这三个方面来探讨C++内存管理问题。1.转载 2020-09-18 00:09:18 · 444 阅读 · 0 评论 -
C++基础——STL常见问题总结
1. STL由哪些组件组成容器(Containers):各种数据结构,如:vector、list、deque、set、map。用来存放数据。从实现的角度来看,STL容器是一种class template。 算法(algorithms):各种常用算法,如:sort、search、copy、erase。从实现的角度来看,STL算法是一种 function template 迭代器(iterators):容器与算法之间的胶合剂,是所谓的“泛型指针”。共有五种类型,以及其他衍生变化。从实现的角度来看,迭代器原创 2020-09-13 18:34:33 · 813 阅读 · 0 评论 -
C++进阶——STL源码之unordered_set与unordered_multiset
STL源码之unordered_set与unordered_multisetstd::set 是关联容器,含有 Key 类型对象的已排序集。用比较函数 Compare 进行排序。搜索、移除和插入拥有对数复杂度。 set 通常以红黑树实现,红黑树具有自动排序的功能,因此set内部所有的数据,在任何时候,都是有序的。std::unordered_set 是含有 Key 类型唯一对象集合的关联容器,依赖于哈希表。搜索、插入和移除拥有平均常数时间复杂度。在内部,元素并不以任何特别顺序排序,而是组织进桶中,元原创 2020-09-11 00:09:31 · 770 阅读 · 0 评论 -
C++进阶——STL源码之unordered_map、unordered_multimap
STL源码之unordered_map、unordered_multimapSTL中几种map的区别map 内部数据的组织,基于红黑树实现,红黑树具有自动排序的功能,因此map内部所有的数据,在任何时候,都是有序的。hash_map 基于哈希表,数据插入和查找的时间复杂度很低,几乎是常数时间,而代价是消耗比较多的内存。底层实现上,使用一个下标范围比较大的数组来存储元素,形成很多的桶,利用hash函数对key进行映射到不同区域进行保存。插入操作:得到key -> 通过hash原创 2020-09-10 00:28:10 · 1736 阅读 · 0 评论 -
C++进阶——STL源码之hashtable
STL源码之hashtablehashtable 是一种在插入、删除、搜寻等操作上也具有 “常数平均时间”(散列表)的数据结构,而且这种表现是以统计为基础,不需依赖输入元素的随机性。STL中hashtable是实现hash_map和hash_set的底层。它解决冲突的方式是开链法,每个放置索引值的节点称为桶节点(也就是该索引值的头结点),桶节点里放着一个value值,一个指向下一个节点的next指针。 维护了一个vector<node *> buckets存放所有桶节点,...原创 2020-09-04 23:53:21 · 1173 阅读 · 0 评论 -
C++进阶——STL源码之map与multimap
STL源码之map与multimapmapmap的特性是,所有元素都会根据元素的键值自动被排序;map的所有元素都是pair,同时拥有实值(value)和 键值 (key),pair的第一个元素视为键值,第二个元素视为实值;map不允许两个元素具有相同的键值。map的迭代器可以用来修改元素的实值(value),修改元素的实值并不会影响map的排列规则;map的迭代器不可以用来改变map的键值,因为修改map的键值会严重破坏map的结构。map对其中的元素进行删除或者新增操作,操作之前的原创 2020-09-02 00:05:29 · 572 阅读 · 0 评论 -
C++进阶——STL源码之set与multiset
STL源码之set与multisetsetset的特性是,所有元素都会根据元素的键值自动被排序,set元素的键值就是实值,实值就是键值,set不允许两个元素有相同的键值。set的元素值不可以通过迭代器来改变,因为set元素就是其键值,关系到set元素的排列规则;如果任何改变set元素值,会严重破坏set组织。set是以rb-tree作为底层机制,又由于set所开放的各种操作接口,rb-tree也提供,所以几乎所有的set操作行为都只是调用rb-tree的操作行为。set源码1. se原创 2020-09-01 23:43:21 · 783 阅读 · 0 评论 -
C++进阶——STL源码之红黑树(_Rb_tree)
STL源码之红黑树STL中Red-black tree(红黑树)class,用来当做STL关系式容器(如set,multiset,map, multimap).里面所用的insertion和deletion方法以 《Introduction to Algorithms》一书为基础,但是有以下两点不同:header不仅指向root,也指向红黑树的最左节点,以便用常数时间实现begin(),并且也指向红黑树的最右边节点,以便 set相关泛型算法(如set_union等等)可以有线性时间表现. 当要删除原创 2020-08-30 20:56:32 · 3668 阅读 · 3 评论 -
C++进阶——STL源码之顺序容器适配器
顺序容器适配器容器适配器是一种利用存在的容器类型采用另一种不同的抽象类型的工作方式实现。stackstack是一种先进后出的数据结构,它只有一个出口;stack允许新增元素、移除元素、取得最顶端的元素;但是除了顶端外不可以存取其他元素;stack没有迭代器。stack在缺省的情况下是以deque作为底部容器来完成所有的工作,元素的操作只有push 和 pop 两个接口。stack也可以使用vector 、 list 、deque 作为底部容器。template<typen原创 2020-08-04 23:27:19 · 303 阅读 · 0 评论 -
C++进阶——STL源码之顺序容器deque
顺序容器dequedeque 是一种双向开口的连续线性空间,所谓双向开口,就是可以在头尾两端分别做元素的插入和删除;与vector 相比,vector可以在头尾两端进行操作,但是其头部的操作效率奇差,无法接受。deque是分段连续线性空间,随时可以增加一段新的空间;与vector相比,vector当内存不够时,需重新分配、复制数据、释放原始空间。deque的迭代器需要处理段之间的过渡,相比于vector的普通指针迭代器要复杂的多。deque的类结构图deque的中控器..原创 2020-08-04 00:15:47 · 430 阅读 · 0 评论 -
C++进阶——STL源码之顺序容器vector
顺序容器vectorvector的数据安排以及操作和array相似,二者的唯一的差别在于空间的运用灵活性:array 是静态空间,一旦配置之后就不能改变;vector是动态空间,随着元素的加入,它的内部机制会自行的扩充空间以容纳新的元素。vector的实现技术,关键在于对其大小的控制以及重新配置时的数据移动效率,一旦vector旧空间满载,vector将会以一种空间配置策略来扩充空间,从而降低配置新空间、数据移动、释放旧空间带来的性能消耗。vector类的结构图通过上面的类结构图,可以知原创 2020-08-02 20:53:44 · 1144 阅读 · 0 评论 -
C++进阶——STL源码之顺序容器array
顺序容器arrayC++ TR1 是ISO/IEC TR 19768 C++ Library Extensions(函式库扩充)的一般名称。TR1 是一份文件,内容提出了对C++标准函式库的追加项目。这些追加项目包括了正则表达式、智能指针、哈希表、随机数生成器等。TR1自己并非标准,他是一份草稿文件;由于tr1中的array实现比较简单,我们先看下tr1::array的实现,然后再看gcc 4.9 std中array的实现。array是一个静态空间,一旦配置了就不能改变。tr1::array原创 2020-08-02 15:33:03 · 381 阅读 · 0 评论 -
C++进阶——STL源码之迭代器(iterators)
STL迭代器在 STL 编程中,容器和算法是独立设计的,即数据结构和算法是独立设计的,连接容器和算法的桥梁就是迭代器了:迭代器是一种行为类似指针的对象,而指针的各种行为中最常见也最重要的使用是:内容提领 和成员访问,所以迭代器会对operator* 和 operator-> 进行重载工作,首先来看下list容器的迭代器实现: template<typename _Tp> struct _List_iterator { typedef _List原创 2020-08-01 21:11:39 · 1534 阅读 · 0 评论 -
C++进阶——STL源码之顺序容器list
list为双向环形链表:list的节点(以下源码的对应版本为 VS2015):template<class _Value_type, class _Voidptr> struct _List_node { // list node _Voidptr _Next; // successor node, or first element if head _Voidptr _Prev; // predecessor node, or last element if hea原创 2020-07-31 00:26:19 · 696 阅读 · 1 评论 -
C++进阶——STL源码之配置器(allocators)
STL提供六大组件,彼此可以组合套用:容器:各种数据结构,如vector,list,deque,set,mao等,用来存放数据 算法:各种常用的算法,如sort,find,copy,for_each等 迭代器:扮演了容器与算法之间的胶合剂 仿函数:行为类似函数,可作为算法的某种策略 适配器:一种用来修饰容器或者仿函数或迭代器接口的东西 配置器:负责空间的配置与管理配置器(allocators):由于STL的操作对象都成存放在容器中,而容器一定需要配置空间;所以它总是隐藏在一切组件的背后,原创 2020-07-30 00:16:27 · 791 阅读 · 0 评论 -
C++基础——字符、字符集、字符串相关
基本概念:字节(Byte):是计算机信息技术用于计量存储容量的一种计量单位,也表示一些计算机编程语言中的数据类型和语言字符。Byte是从0-255的无符号类型,所以不能表示负数[3]。字符:和字节不同,任何一个文字或符号都是一个字符,但不同的编码格式使一个字符所占的内存不同(比如:GBK编码中汉字占2个字节,UTF-8 编码中一个汉字占 3个字节)。编码规范:为了显示字符,国际组织就制定了编码规范,希望用不同的二进制数来表示不同的字符。字库表:一个相当于存储了编码规范中能显示的所有字符...原创 2020-07-21 19:50:09 · 760 阅读 · 0 评论 -
C++基础——动态内存分配的总结
C中的动态内存分配C中的动态内存分配C++中的内存分配new和malloc的区别属性:new/delete是C++关键字,需要编译器支持。malloc/free是库函数,需要头文件支持c。参数:使用new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算。而malloc则需要显式地指出所需内存的尺寸。返回类型:new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换,故new是符合类型安全性的操作符。而malloc...原创 2020-07-20 22:19:23 · 1173 阅读 · 2 评论 -
C++基础——多字节值与字节序
多字节值与字节序大于8位(一字节)的值称为多字节量,在内存中存储多字节量有两种方式:小端:处理器储存多字节值的最低有效字节于较低的内存位置,则该微处理器就是小端处理器;大端:微处理器储存多字节值的最高有效字节于较低的内存位置,则该处理器为大端处理器。对于跨平台应用,字节序的两种处理方式所有数据以文字的方式写入文件;多字节数值以一串十进制数字,每个数字一个的写入,这会浪费磁盘空间。 工具先转换字节序,然后再把转换后的数据写进二进制文件。字节序的判断/**返回1小端*返回0原创 2020-07-19 19:23:43 · 538 阅读 · 0 评论 -
C++基础——断言(assert)的实现
断言(assert)断言(assert)是一行检查表达式的代码;当表达式求值为真,一切正常;但若表达式求值为假,则暂停程序,打印消息,并在可行的情况下启动调试器。断言(assert)是一个宏,而非函数。断言的使用#include <assert.h>using namespace std;float division(float a, float b) { assert(b != 0); return a / b;}int main() { int a原创 2020-07-19 15:55:04 · 1944 阅读 · 0 评论 -
C++基础——对象的内存布局
对齐和包裹事实上每种数据类型有其自然的对齐方式,使用内存对齐的原因如下:现在计算机内存空间都是按照byte字节划分的,理论上讲对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址上访问,这就需要各种数据类型按照一定的规则在空间上排列,而不是一个接一个的排放,这就是内存对齐。 cpu对内存的读取不是连续的而是分块读取的,块的大小只能是2i个字节数,从cpu的读取性能和效率来考虑,若读取的数据未对齐,则需要两次总线周期来访问内存,因而效率会大打折扣 另.原创 2020-07-19 15:06:34 · 263 阅读 · 0 评论 -
C++基础——C/C++的内存布局
程序的内存布局可执行映像当生成C/C++程序时,链接器会创建可执行文件,比如像window系统上可执行文件.exe;可执行程序总是包含程序的部分映像,程序执行时此部分映像会置于内存中,称为“部分”映像的原因是由于程序把可执行的映像置于内存中,一般也会分配额外的内存。可执行映像分为几个相连的块,这些块称为段或节;每个操作系统的可执行文件布局方式都有些差异,同一个操作系统的不同执行文件也会有些微差异,但映像文件一般最少有以下4段组成:1. 代码段:此段包含程序中的定义的全部函数的可执行机器码原创 2020-07-18 23:21:11 · 168 阅读 · 0 评论 -
C++基础——C固有的不可移植的特性
C固有的不可移植的特性为了支持低级编程,C语言定义了一些固有不可移植特性:算术类型的大小随机型不同而变化, 位域 volatile限定符volatile具体见:C++基础——Volatile关键字位域“ 位域 “ 或 “ 位段 “(Bit field)为一种数据结构,可以把数据以位的形式紧凑的储存,并允许程序员对此结构的位进行操作。这种数据结构的一个好处是它可以使数据单元节省储存空间,当程序需要成千上万个数据单元时,这种方法就显得尤为重要。第二个好处是位段可以很方便的访问一个整数值原创 2020-07-18 18:09:00 · 220 阅读 · 0 评论 -
C++基础——virtual相关总结
virtual相关总结静态函数与虚函数静态函数不可以声明为虚函数,同时也不能被const 和 volatile关键字修饰,原因如下:static成员函数不属于任何类对象或类实例,所以即使给此函数加上virutal也是没有任何意义; 虚函数依靠vptr和vtable来处理。vptr是一个指针,在类的构造函数中创建生成,并且只能用this指针来访问它,静态成员函数没有this指针,所以无法访问vptr。构造函数与虚函数构造函数不可以声明为虚函数;原因如下:1. 从存储空间角度虚函数.原创 2020-07-18 16:50:38 · 195 阅读 · 0 评论 -
C++基础——虚继承以及实现原理
多继承多继承(Multiple Inheritance)是指从多个直接基类中产生派生类的能力,多继承的派生类继承了所有父类的成员。尽管概念上非常简单,但是多个基类的相互交织可能会带来错综复杂的设计问题,命名冲突就是不可回避的一个;多继承时很容易产生命名冲突,即使我们很小心地将所有类中的成员变量和成员函数都命名为不同的名字,命名冲突依然有可能发生,比如典型的是菱形继承,如下图所示:类 A 派生出类 B 和类 C,类 D 继承自类 B 和类 C,这个时候类 A 中的成员变量和成员函数继承到类 D 中变原创 2020-07-17 00:17:33 · 702 阅读 · 0 评论 -
C++基础——虚指针(vptr)与虚基表(vtable)
vptr与vtable手动操作vptr 来访问vtable中的虚函数,如以下测试程序:#include <iostream>#include <memory>using namespace std;typedef void (*func)(void);class Base {public: virtual void f() { cout << "Base::f" << endl; } virtual void g() { cout原创 2020-07-16 11:15:39 · 3963 阅读 · 2 评论 -
C++基础——智能指针 shared_ptr 和 weak_ptr 的使用
shared_ptrshared_ptr 是一个标准的共享所有权的智能指针,允许多个指针指向同一个对象,定义在 memory 文件中,命名空间为 std。shared_ptr最初实现于Boost库中,后由 C++11 引入到 C++ STL。shared_ptr 利用引用计数的方式实现了对所管理的对象的所有权的分享,即允许多个 shared_ptr 共同管理同一个对象。shared_ptr 的基本用法#include <iostream>#include <memory原创 2020-07-15 14:27:32 · 5961 阅读 · 0 评论 -
C++基础——Volatile关键字
Volatile关键字Volatile:易变的在介绍C/C++ Volatile关键词的”易变”性前,先让我们看看以下的两个代码片段,以及他们对应的汇编指令 (以下用例的汇编代码,均为VS 2008编译出来的Release版本):测试用例一:非Volatile变量 b = a + 1;这条语句,对应的汇编指令是:lea ecx, [eax + 1]。由于变量a,在前一条语句a = fn(c)执行时,被缓存在了寄存器eax中,因此b = a + 1;语句,可以直接使用仍旧在寄存器eax中.转载 2020-07-10 14:37:13 · 391 阅读 · 0 评论 -
C++基础——类型转换的使用
类型转换隐式类型转换1. 内置数据类型的隐式转换隐式转换的基本原则:由低精度向高精度的转换,若不满足该原则,编译器会给出警告。#include <iostream>void func(double d) {}int main() { int iValue = 1; double dValue = 9.0; double dSum = iValue + dValue;//iValue 会被隐式转换到 double iValue = true; //bo原创 2020-07-10 13:41:37 · 363 阅读 · 0 评论 -
C++基础——智能指针auto_ptr 和unique_ptr的使用
智能指针的使用由于C++语言没有自动的内存回收机制,需要自己管理对象的new与delete;流程太复杂,最终导致没有delete,异常导致程序过早退出,没有执行delete的情况并不罕见,用智能指针便可以有效缓解这类问题。对于编译器来说,智能指针实际上是一个栈对象,并非指针类型,在栈对象生命期即将结束时,智能指针通过析构函数释放有它管理的堆内存。所有智能指针都重载了“operator->”操作符,直接返回对象的引用,用以操作对象。访问智能指针原来的方法则使用“.”操作符。访问智能指针包含...原创 2020-07-09 19:35:18 · 1061 阅读 · 0 评论 -
C++基础——宏的相关使用
宏的相关使用预处理命令可以改变程序设计环境,提高编程效率,它们并不是 C本身的组成部分,不能直接对它们进行编译,必须在对程序进行编译之前,先对程序中这些特殊的命令进行“预处理” 。经过预处理后,程序就不再包括预处理命令了,最后再由编译程序对预处理之后的源程序进行编译处理,得到可供执行的目标代码。C 提供的预处理功能有三种,分别为宏定义、文件包含和条件编译。宏中包含的特殊符号先来看下这段代码(来自 unreal4的源码),来理解下其中用到的特殊符号:#define IMPLEMENT_NET原创 2020-07-08 23:06:06 · 239 阅读 · 0 评论 -
C++基础—— 关键字 extern
C++关键字externextern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义,此外extern也可用来进行链接指定。extern “C” 的使用在C++环境下使用C函数的时候,常常会出现编译器无法找到obj模块中的C函数定义,从而导致链接失败的情况,在Android JNI 开发过程中我们经常使用以下的代码,处理这个问题:extern "C" { JNIEXPORT void JNICALL Java_com_原创 2020-07-08 12:13:21 · 357 阅读 · 0 评论 -
3D数学基础——Rotator类的C++实现
Rotator类的C++实现FRotator类用来以欧拉角形式保存方位,使用pitch-yaw-roll进行约定,类的定义如下(来自于unreal4源码):struct FRotator{public: float Pitch; float Yaw; float Roll;public: static CORE_API const FRotator ZeroRotator;public: inline FRotator() { }; explicit inli原创 2020-07-08 00:10:13 · 1016 阅读 · 1 评论 -
C++基础——引用和指针的区别
C++引用引用的实现原理引用一般被称为变量的别名,定义的时候必须初始化绑定一个指定的对象,且中途不可更改绑点原创 2020-07-06 18:05:37 · 445 阅读 · 0 评论 -
C++基础—— explicit 关键字
explicit 关键字在c++ 中,一个参数的构造函数(或者除了第一个参数之外其余参数都有默认值的多参构造函数),承担着两个作用:1. 构造器2. 隐含的类型转换操作符#include <iostream>class MyClass{public: MyClass(int n) { size = n; }private: int size;};int main(){ MyClass myClass(10);//显示调用构造函数 MyCla原创 2020-07-03 11:30:11 · 292 阅读 · 0 评论 -
C++基础——static关键字的使用
static关键字静态局部变量静态局部变量在程序执行到该对象的声明处时被首次初始化,在以后的函数调用不再进行初始化; 静态局部变量一般在声明处初始化,如果没有显式初始化,会被程序自动初始化为0; 静态局部变量始终驻留在全局数据区,直到程序运行结束。但其作用域为局部作用域,不能在函数体外面使用它;#include <iostream>using namespace std;void func() { static int count = 0; count++; c原创 2020-06-29 14:30:22 · 149 阅读 · 0 评论 -
C++基础——模板的介绍与使用
模板模板是一种使用无类型参数来产生一系列函数或类的机制;若一个程序的功能是对某种特定的数据类型进行处理,则可以将所处理的数据类型说明为参数,以便在其他数据类型的情况下使用,这就是模板的由来;模板是以一种完全通用的方法来设计函数或类而不必预先说明将被使用的每个对象的类型;通过模板可以产生类或函数的集合,使它们操作不同的数据类型,从而是我们不需为每一种数据类型产生一个单独的类或函数(这些将由编译器来处理)。函数模板定义模板格式模板函数定义的一般形式如下所示:template <typ原创 2020-06-21 23:26:28 · 382 阅读 · 0 评论 -
C++基础——friend函数和friend类的使用
friend函数和friend类友元机制允许一个类将对其非公有成员的访问权授予指定的函数或者类;友元的声明关键字是friend开始,它只出现在类定义的内部;友元声明可以出现在类中的任何位置:友元不是授予友元关系的那个类的成员,所以它们不受其声明出现部分的访问控制影响。friend函数在定义一个类的时候,可以把一些函数(包括全局函数和其他类的成员函数)声明为“友元”,这样那些函数就成为该类的友元函数,在友元函数内部就可以访问该类对象的私有成员了。将全局函数声明为友元:friend 返回.原创 2020-06-21 15:58:53 · 1914 阅读 · 0 评论 -
C++基础——C程序的存储空间布局
C程序的存储空间布局 正文段(.text)这是由CPU执行的机器指令部分。通常,正文段是可共享的,所以即使是频繁执行的程序(如文本编辑器、C编译器和shell等)在存储器中也只需有一个副本,另外,正文段常常是只读的,以防止程序由于意外而修改其指令;程序的所有指令会存放在这个区域,这是已经编译后的机器码。初始化数据段(.data)通常将此段称为数据段,它包含了程序中需明确地赋初值的变量(已经初始化的非零全局变量)。例如,C程序中任何函数之外的声明:int ...原创 2020-06-20 18:26:00 · 290 阅读 · 0 评论