正向迭代器(iterator)作为最常用的迭代器类型,实现了从容器起始位置到末尾位置的遍历,但在实际开发中,我们常常需要反向遍历容器(如从末尾元素向前输出、逆序处理数据等),这就需要反向迭代器(reverse_iterator...类型萃取:通过iterator_traits自动提取正向迭代器的相关类型(如value_type、reference),避免显式传递模板参数,提高通用性。...3.1 通用反向迭代器实现(ReverseIterator.h) 我们实现的反向迭代器需要支持以下核心功能: 接收正向迭代器、引用类型、指针类型作为模板参数。...,Ref为引用类型,Ptr为指针类型 template struct ReverseIterator { typedef...),Ref是元素的引用类型(如T&、const T&),Ptr是元素的指针类型(如T*、const T*)。
所以可以利用类的构造函数和析构函数,将需要分配资源的对象进行一层封装,将其获取资源和释放资源分别绑定到构造函数和析构函数里,这样当该对象生命周期结束,就会自己释放资源。...::value_type tmp=*iter; tmp++; return tmp; } 每个类型I的迭代器都会储存指向元素的类型value_type,像原生指针、const...int a=10; int &b=a; int &&c=10; 如果我们就想用左值引用绑定到左值上,那就需要用到move()了。...注意get()到的指针不要再初始化另一个智能指针。...基类必须要有虚函数,因为 dynamic_cast 是运行时类型检查,需要运行时类型信息,而这个信息是存储在类的虚函数表中。
Line 1034: Char 34: runtime error: applying non-zero offset 4 to null pointer (stl_vector.h) SUMMARY.../include/c++/9/bits/stl_vector.h:1043:34 错误原因 根据报错信息,问题出现在这一行代码: if (a[nums[i]] !...= 0) 错误提示是在stl_vector.h文件中,发生了对空指针的非零偏移操作。问题在于你创建的vector a没有初始化,它的大小是0,因此不能通过索引访问其中的元素。...) 再次修改 问题出现在这一行代码: nums[--count] = *it; 在这里,你试图通过递减count来将元素赋值给nums数组,但这样的方式会导致负数索引。...负数索引在C++中是无效的,会导致未定义行为。 为了正确地处理负数和保持原始顺序,我们可以使用另外一个数组来存储不重复的元素,并在遍历uniqueSet时按顺序将元素存储到这个数组中。
1)引用是与初始值绑定到一起,而不是将初始值拷贝给引用。...2)引用无法重新绑定,一直与初始对象绑定到一起,因此必须初始化。 3)引用不是对象,只是已存在对象的别名,不能定义引用的引用。以引用作为初始值,实际上是以与引用绑定的对象作为初始值。...4)非常量引用不能与字面值或表达式绑定到一起。 15.指针 1)指针本身是一个对象,允许赋值和拷贝,而且在生命周期内可以先后指向不同的对象。 2)无须在定义时赋初值。...3)引用不是对象,没有实际地址,不能定义指向引用的指针。 16.C++11中,最好用 nullptr来初始化空指针。不能把 int变量直接赋给指针,下面的代码是错误的。...// ps是一个指针,对象是指向 char的常量指针 4 // 第2行代码的两种解释方案 5 const (char) * cstr; // 错误,基本类型为 char,解释成指向 const
引用的特点 必须初始化:引用在声明时必须初始化,不能先声明后赋值。 不可重新绑定:引用一旦绑定到一个变量,就不能再绑定到其他变量(即:不能改变指向)。...多个别名:一个变量可以有多个引用 无空引用:引用必须指向一个有效的对象,不能像指针那样可以为 nullptr。 自动解引用:使用引用时不需要像指针那样使用 * 来解引用。 3. 引用的使用 3.1....sizeof的含义不同,引用结果大小为引用类型的大小,指针始终为地址空间所占字节个数 指针容易出现空指针和野指针 二,内联函数inline 1....,不会与整数类型混淆 可能被误认为是整数类型(如 int) 重载函数解析 能正确区分指针和整数重载 可能导致重载函数解析错误 代码清晰性 明确表示空指针,语义清晰 语义不够明确,可能被误解为整数 0...nullptr 明确表示指针类型,能正确匹配指针重载。 代码清晰性 nullptr 明确表示空指针,提高了代码的可读性和语义清晰性。
扩容后旧地址失效,必须更新新的堆指针。3. 需要支持空容器状态,用空指针表示。引用必须绑定到对象,无法延迟绑定或置空。- 引用不能在扩容时重新绑定新内存。...叶子节点间通过指针快速遍历。3. 插入/分裂/合并时,节点间指针频繁更新。引用不能在运行时变更绑定关系。- 无法表示“空孩子指针”。...哈希冲突需要通过链表或指针串联节点。引用无法处理哈希桶为空的场景。- 无法在 rehash 时更新绑定。...引用不能是空的,所以指针是唯一选择。泛型友好vector 支持任意类型 T,不要求 T 必须可引用。用指针实现不会对模板参数类型提出额外约束。...,深入引用初始化必须绑定 扩展到变量重要数据结构设计 ,这个是和很大话题 b++tree,红黑树 这个都是高频题目在参数传递过程中,在过程过程中,右值引用类型丢失这个隐藏的内容我怎知道的但凡阅读过源码
2.3 尾置返回类型与类型转换 2.4 函数指针和实参推断 1 定义模板 1.1 函数模板 template // 模板参数列表,不能为空,用逗号隔开,每个类型参数前必须使用...例如: cout << compare(1, 0) << endl; 实参类型是int,编译器会推断出模板实参为int,并将它绑定到模板参数T。...非类型参数可以是一个整型,或者是一个指向对象或函数类型的指针或(左值)引用。 非类型模板参数的模板实参必须是常量表达式。...绑定到指针或引用非类型参数的实参必须具有静态的生存期,即不能用一个非static局部变量或动态对象作为指针或引用非类型模板参数的实参。...1.6 效率与灵活性 unique_ptr在编译时绑定删除器,避免了间接调用删除器的运行时开销。 shared_ptr在运行时绑定删除器,使用户重载删除器更为方便。
例如:数字 10,表达式 a + b 的结果 代码示例一:引用绑定常量 #include using namespace std; int main() { //错误写法...④编译器拦截:为了防止这种逻辑混乱,编译器强制规定,非常量左值引用不能绑定到右值上。 为什么 const int& rd = a + b; 是正确的?...③续命(核心):原本 a + b 的结果在这一行执行完就该消失了,但因为被 rd(常量引用)引用了 温馨提示:编译器规定,这个临时变量的生命周期将延长到与引用 rd 一样长。...这种“指东打西”的行为会导致极其严重的 Bug,因此 C++ 规定:除非是常量引用,否则禁止绑定到因类型转换产生的临时变量上。...空值 允许为空 (nullptr) 严禁为空 ①引用不需要检查空值(理论上),这让代码更简洁。 ②但指针需要满地写 if(p)。
看起来好像编译器根本不鸟p的值是什么,只介意p的类型。别着急,咱先吊吊胃口,把答案留到后面的章节。现在,我们所能知道的是,编译器准确地知道要调用哪个函数。这就是所谓的“静态绑定”。...*fptr 绑定fptr到对象obj,而 ->*fptr 则绑定fptr到指针p所指向的对象。(还有一个 重要的区别 是:我们可以重载后者,却不能重载前者)。在 (obj....它让这些繁琐的定义变得清晰起来。关键是,fptr是什么类型?它的类型是: int (Foo::*) (char*); 或者等价地说——FPTR。...= static_castchar*)>(fptr); 这一行却是正确的!...而在我们的例子中 this 指针并没有被解引用,所以,编译器放了我们一马(翻译君表示,这其实跟编译器没有关系,即使我们在成员函数中使用this指针,编译照样能通过,只不过在运行时会crash)。
扩容后旧地址失效,必须更新新的堆指针。3. 需要支持空容器状态,用空指针表示。 - 引用必须绑定到对象,无法延迟绑定或置空。- 引用不能在扩容时重新绑定新内存。 std::map 1....叶子节点间通过指针快速遍历。3. 插入/分裂/合并时,节点间指针频繁更新。 - 引用不能在运行时变更绑定关系。- 无法表示“空孩子指针”。...哈希冲突需要通过链表或指针串联节点。 - 引用无法处理哈希桶为空的场景。- 无法在 rehash 时更新绑定。...• 引用不能是空的,所以指针是唯一选择。 3 泛型友好 • vector 支持任意类型 T,不要求 T 必须可引用。 • 用指针实现不会对模板参数类型提出额外约束。...c++语法知识,深入引用初始化必须绑定 扩展到变量重要数据结构设计 ,这个是和很大话题 b++tree,红黑树 这个都是高频题目 • 在参数传递过程中,在过程过程中,右值引用类型丢失这个隐藏的内容我怎知道的
“这个过程可能会涉及到类型推断和类型标注,但类型标注是可选的,所以不用太担心。” “默认情况下,变量绑定的值是不能改变的,也就是说,一旦你把一个值绑定到一个变量,那这个变量的值就不能改变了。”...如果变量是可变的,也就是用 mut 声明的,那就可以对其进行重新赋值。” “比如在我们的代码中的这两行。上面一行就是变量绑定,非常简洁。...“程序员可以解引用任何指针,包括空指针、悬挂指针或野指针,这可能导致运行时错误,如段错误。” “C++ 编译器通常不检查这些错误,它们往往在运行时才显现出来。”...用途 两者都允许通过解引用间接访问和操作变量。 两者都允许通过解引用间接访问和操作变量。 安全性和错误处理 Rust在编译时执行所有权和借用规则,确保不会解引用空指针或悬空引用。...不安全的解引用会阻止代码编译,提高程序安全性。 C++允许解引用任何指针,包括空指针,悬空指针,或野指针,可能导致运行时错误,如段错误。C++编译器通常不检查这些错误,它们通常只在运行时出现。
扫一眼你就能发现,最重要的肯定是我画圈的两个头文件 。 其实最重要的是 stl_vector.h,最后一个头文件是用来实现vector的类型。...而下面的模板是双参数类型是且类型一致的,一个int一个char,只能将就上面的模板。 库里面是重载了一个int版本的来暂时解决这个问题: 源码如图。不过没有根本解决问题。...麻烦,不推荐) 2.6析构函数 思路:把空间释放,然后指针全部置空,这片空间的起始地址是_start指向,而delete[ ]的作用是:自动释放该地址对应的整块连续内存 2.7pop_back 思路:这是尾删...resize考虑到 T 的类型可能不一定是字面量常量,也可能是类类型,而匿名对象可以适配任意类型(包括内置类型和类类型) 于是就用匿名对象作为缺省值。 难道内置类型也有匿名对象?...pos 到 end(_finish - 1) 的数据挪动出错,因为pos和end不在一片空间,而且对pos的操作都会导致野指针 解决办法是:保存 pos到旧空间_start的相对长度len ,然后让pos
原因:因为在编译时对象就绑定了函数地址,和指针空不空没关系。 说说使用指针需要注意什么?...用free或delete释放了内存之后,立即将指针设置为NULL,防止“野指针” c++指针和引用的区别 指针可以被重新赋值指向其他变量,而引用一旦绑定到一个变量上就不能再绑定到其他变量上。...指针可以被声明为nullptr,表示指向空地址,而引用必须始终绑定到一个有效的对象上。 指针可以进行算术运算,比如加减,以及指针与整数进行加减运算,而引用只能作为变量的别名使用,不能进行算术运算。...指针可以指向指针,而引用只能绑定到一个变量上。...) 注意在使用 void * 指针时,为了正确解引用指针并获取其指向的值,需要在使用前进行类型转换。
compare(const char (&p1)[3], const char(&p2)[4]) 非类型参数可以是一个整型,或者是一个指向对象或者函数类型的指针或(左值)引用 绑定到非类型参数的实参必须是一个常量表达式...绑定到指针或者引用非类型参数的实参必须具有静态的生存期 1.2 编写类型无关的代码 编写泛型代码的两个重要原则: 模板中的函数参数是const的引用 函数体中的条件判断仅使用<比较运算 通过将函数参数设定为...毕竟i是一个左值,而通常我们不能将一个右值引用绑定到一个左值上。...理解std::move 虽然不能直接将一个右值引用绑定到一个左值上,但可以用move获得一个绑定到左值上的右值引用。...T被绑定到const char debug_rep(const sring&),要求从const char*到string的类型转换 对给定实参来说,两个模板都提供精确匹配(第二个模板需要进行一次数组到指针的转换
绑定到指针或引用非类型参数的实参必须具有静态的生存期。...shared_ptr,因为不同对象可以共享指针所有权,需要在运行时可以方便的重载删除器;unique_ptr,独占指针,不需要重载删除器,自定义删除器的类型需要在定义 unique_ptr时一并给出。...如果不能从函数指针类型确定模板实参,则产生错误。...const右值 template void f(const T&); // 绑定到左值和 const右值 某些函数需要将其一个或多个实参连同类型不变地转发给其它参数...对于第一个模板,T的类型为 char[3];对于第二个模板,T的类型是 const char;对于普通非模板函数,要求从 const char*到 string的类型转换。
前文我们了解到了正向迭代器是基于原生指针的封装实现,反向迭代器的逻辑与正向迭代器的逻辑正好相反,代码应该高度相似,因此在学习了stack与queue之后,明白了适配器思想,我们就复用正向迭代器代码实现反向迭代器...,我们需要自己传递参数,而有了萃取技术后,我们可以得到对应的类型,因此就不需要传递很多参数。...,支持偏特化的迭代器萃取以后就不需要给了,因为reverse_iterator 内部可以通过迭代器萃取获取数据类型。...,begin与rend,end与rbegin,所以解引用访问的是当前位置的前一个位置,这样返回解引用rbegin时,返回上一个节点,即返回有效节点的最后一个节点,解引用rend就会正好返回哨兵节点。...• 其次就是负数和减号,要进行区分,将所有的负数-x转换为0-x,因为我们实现的代码考虑到乘除的情况,针对括号内的符号,我们不能直接变号处理。
常量指针(char* const)必须初始化,而指向常量指针的普通指针(char* const*)无需初始化。...b = a; auto c = a; 上述就不一样了,因为auto c = a;你是赋值还是引用,所以对于引用来说就必须带上& 2️⃣在同一行定义多个变量 当在同一行声明多个变量时,这些变量必须是相同的类型...for (auto& e : array) e *= 2; 但我有个疑惑,就是前面我们在学习引用的时候就了解到,引用只能绑定到一个已经存在的对象,这里为什么一个e却能绑定到数组当中的每一个元素,数组当中的每一个元素不都是不同的空间吗...不清楚大家有这样的疑惑没,如果大家也有这样的疑惑,我们真是同道中人,经过我的查阅,下面为大家解惑: 在C++的范围for循环中,auto& e 在每次迭代时都会创建一个新的引用变量,并将其绑定到当前处理的元素上...四、指针空值nullptr(C++11) 4.1 C++98中的指针空值 在良好的C/C++编程习惯中,声明一个变量时最好给该变量一个合适的初始值,否则可能会出现 不可预料的错误,比如未初始化的指针
基本内置类型:编译器内置的基本类型,包括算数类型(字符、整型数、布尔值、浮点数)和空类型void 复合类型:基于其他类型定义的类型,包括数组、C风格字符串、指针、引用、C风格结构体(POD)和联合体(...引用为对象起了另一个名字,定义引用时程序把引用和它的初始值绑定在一起,一旦初始化完成引用将一直和它的初始值对象绑定在一起。...因为无法令引用重新绑定到另一个对象,因此引用必须初始化 因为引用不是一个对象,所以不能定义引用的引用 指针 指针是指向(point to)另外一种类型的复合类型。 1....使用未经初始化的指针是引发运行时错误的一大原因,如果使用了未经初始化的指针,那么指针所占空间的当前内容将被当成一个地址值,当这个地址值指向的内存空间中正好有内容时,就可能引发难以预料的后果。...C++11中我们可以用字面量nullptr初始化指针来得到空指针,它可以被转化成任意其他的指针类型。
(3)使用指针作为函数的参数虽然也能达到与使用引用的效果,但是,在被调函数中同样要给形参分配存储单元,且需要重复使用"*指针变量名"的形式进行运算,这很容易产生错误且程序的阅读性较差;另一方面,在主调函数的调用点处...常引用声明方式:const 类型标识符 &引用名=目标变量名; 例1 1 int a ; 2 const int &ra=a; 3 ra=1; //错误 4 a=1; //正确 例2 1 string...而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误。 2)有些集成化的调试工具可以对const 常量进行调试,但是不能对宏常量进行调试。 20.简述数组与指针的区别?...编译器不能发现该错误,运行时错误 (2) 用运算符sizeof 可以计算出数组的容量(字节数)。...引用必须被初始化,指针不必。 引用初始化以后不能被改变,指针可以改变所指的对象。 不存在指向空值的引用,但是存在指向空值的指针。 22.基类的析构函数不是虚函数,会带来什么问题?