C++设计的禁忌与救赎:特殊类设计
业务处理时常常会出现一些特定的要求,需要设计出特殊的功能,下面介绍几个常见的特殊类设计 请设计一个类,不能被拷贝涉及拷贝的只有拷贝构造和赋值重载,把这些禁用了就行了 123456789class CopyBan{ // ...private: CopyBan(const CopyBan&); CopyBan& operator=(const CopyBan&); //...}; 对于 C++98,直接设置为私有即可,这样类外就无法访问了,只声明不定义:不定义是因为该函数根本不会调用,定义了其实也没有什么意义,不写反而还简单,而且如果定义了就不会防止成员函数内部拷贝了 12345678class CopyBan{ // ... CopyBan(const CopyBan&) = delete; CopyBan& operator=(const CopyBan&) = delete; //...}; 对于 C++11,直接在默认成员函数后跟上 =...
C++内存列传之RAII宇宙:智能指针
智能指针是 C++ 中用于自动管理动态内存的类模板,它通过 RAII(资源获取即初始化)技术避免手动 new / delete 操作,从而显著减少内存泄漏和悬空指针的风险 为什么需要智能指针?123456789101112131415161718192021222324252627282930int div(){ int a, b; cin >> a >> b; if (b == 0) throw invalid_argument("除0错误"); return a / b;}void Func(){ int* p1 = new int; int* p2 = new int; cout << div() << endl; delete p1; delete p2;}int main(){ try { Func(); } catch (exception& e) { cout << e.what()...
C++日新月异的未来代码:C++11(下)
接上篇,继续学习C++11的常用新特性 lambda表达式引入lambda 表达式是一种匿名函数对象,允许在代码中直接定义和使用小型的函数,无需额外定义函数或函数对象类,这么讲,感觉还是太理论了,下面将通过特定场景介绍其使用: 1234567891011121314151617181920212223242526272829303132333435struct Goods{ string _name; // 名字 double _price; // 价格 int _evaluate; // 评价 Goods(const char* str, double price, int evaluate) :_name(str) , _price(price) , _evaluate(evaluate) {}};struct ComparePriceLess{ bool operator()(const Goods& gl, const Goods& gr) { return gl._price...
C++日新月异的未来代码:C++11(上)
C++11 能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅功能更强大,而且能提升程序员的开发效率,公司实际项目开发中也用得比较多,所以我们要作为一个重点去学习 统一的列表初始化普通{ }初始化123456789101112struct Point{ int _x; int _y;};int main(){ int array1[] = { 1, 2, 3, 4, 5 }; int array2[5] = { 0 }; Point p = { 1, 2 }; return 0;} 在 C++98 中,标准允许使用花括号{}对数组或者结构体元素进行统一的列表初始值设定 12345678910111213141516struct Point{ int _x; int _y;};int main(){ int x1 = 1; int x2{ 2 }; int array1[]{ 1, 2, 3, 4,...
C++寻位映射的究极密码:哈希扩展
位图和布隆过滤器是基于哈希的一种常见应用,通常用来处理大体量数据,提升查找数据的效率 位图给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中? 放在哈希表中去寻找?不,这并不现实,因为哈希表的存储也是需要空间消耗的,况且是 40 亿个数据,如此庞大的数据计算机一般是很难存储 因此就诞生了位图的概念,位图简单来说就是把每个数按照哈希函数的计算,存储到每个比特位上。数据是否在给定的整形数据中,结果是在或者不在,刚好是两种状态,那么可以使用一个二进制比特位来代表数据是否存在的信息,如果二进制比特位为 1,代表存在,为 0 代表不存在 位图的结构1234567891011template<size_t N>class bitset{public: bitset() { _a.resize(N / 32 + 1); }private: vector<int> _a;}; 开辟一个 vector 数组 _a,这里我们以 int 作为位图的基本单位,那么就是把每个数据存储到...
C++效率掌握之STL库:unordered_map && unordered_set底层剖析
看了前面的底层封装后,其实封装的过程及方法都大差不差,unordered_map && unordered_set 也是如此,所以本篇就简单提及一些细节,具体最详细的一些部分可以去看前面的文章 传送门:C++效率掌握之STL库:list底层剖析及迭代器万字详解 传送门:C++效率掌握之STL库:map && set底层剖析及迭代器万字详解 unordered_map、unordered_set的基本结构🚩unordered_set: 123456789101112131415161718192021222324252627282930313233template<class K, class V>class unordered_set{ struct SetKeyOfT { const K& operator()(const K& key) { return key; } };public: typedef typename...
C++寻位映射的奇幻密码:哈希
哈希,用于将任意大小的数据映射为固定长度的数值(哈希值),这个过程通过哈希函数实现,其核心目标是高效地存储、查找和验证数据 什么是哈希? 在学哈希之前,我们对于数据的查找通常是建立于顺序表,树形结构的基础上进行的查找,但是随着数据量越来越庞大,数据的随机性和容量越发严峻 理想的搜索方法: 可以不经过任何比较,一次直接从表中得到要搜索的元素如果构造一种存储结构,通过某种函数( hashFunc )使元素的存储位置与它的关键码之间能够建立一一映射的关系,那么在查找时通过该函数可以很快找到该元素 因此就在此基础上发展出了一种平均时间复杂度几乎为 O(1) 的数据查找方式,哈希,也称为散列 哈希的常见实现方法直接定址法 对于一段相对集中的数据段,就可以使用直接定址法,这里最大的数是 30,最小的数是15,创建一个大小为 15 的数组,将所有值映射到数组上 优点: 简单、均匀缺点: 需要事先知道关键字的分布情况使用场景:...
C++效率掌握之STL库:map && set底层剖析及迭代器万字详解
map、set 的封装可以说是很天才的底层结构了,本篇将对其结构进行详细的解析,虽然会很复杂且难以理解,但是学完成就感满满,而且对底层理解和面试很有帮助 map、set的基本结构 通过查看官方文档,截取部分关键代码,我们可以发现 set 虽然事 k-k 类型,map 是 k-v 类型,但是实际上这两个类共用一个红黑树,准确来说是共用同一个模板类型,set 是 <K,K>,map 是 <K,pair<K,V>>,下面会进行详细解析 size_type node_count:用于记录红黑树节点数量,跟踪树的大小 link_type header:是指向红黑树头节点的指针 Value value_field:存储节点的值 那么下面我们将自己实现简单的 set 和 map 类: map、set模拟实现初步定义12345678910111213template<class K>class set{private: RBTree<K, K> _t;};template<class K, class...
C++色彩博弈的史诗:红黑树
红黑树是一种自平衡二叉查找树,每个节点都带有颜色属性,颜色或为红色或为黑色,可以理解为 AVL 树的进阶版,建议系统学习完 AVL 树再来看本篇博客 传送门:C++漫步结构与平衡的殿堂:AVL树 红黑树的概念 红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是 Red 或 Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保最长路径的节点数量不超过最短路径节点数量的两倍(刚好两倍是可以的),因而是接近平衡的 一个合格的红黑树需要满足以下条件: 每个结点不是红色就是黑色 根节点是黑色的 如果一个节点是红色的,则它的两个孩子结点必须是黑色的,任何路径都没有连续的红色节点,也就是说可以有连续的黑色节点,但不可能一颗红黑树全是黑色节点 ...
C++漫步结构与平衡的殿堂:AVL树
二叉搜索树有其自身的缺陷,假如往树中插入的元素有序或者接近有序,二叉搜索树就会退化成单支树,时间复杂度会退化成 O(N),因此 map、set 等关联式容器的底层结构是对二叉树进行了平衡处理,即采用平衡树来实现 AVL树的概念 我们已经从多种树型结构走到现在,每一次变化都是为了提高搜索的效率,即时间复杂度 二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率低下,因此发明了 AVL 树 那么什么是AVL树呢? 当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过 1 (需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度 一棵 AVL 树或者是空树,应该是具有以下性质的二叉搜索树: 它的左右子树都是 AVL 树 左右子树高度之差(简称平衡因子)的绝对值不超过 1(-1/0/1) 二叉搜索树在理想情况下时间复杂度与二叉平衡搜索树相同,均为 $O(log_2...