
命名空间
在C/C++中,变量、函数和后面要学习的类都是大量存在的,这些变量、函数和类的名称都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或者名字污染,namespace关键字的出现就是针对这种问题的。 定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。 注:...
共 27 篇文章

在C/C++中,变量、函数和后面要学习的类都是大量存在的,这些变量、函数和类的名称都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或者名字污染,namespace关键字的出现就是针对这种问题的。 定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。 注:...

C语言中我们用到的最频繁的输入输出方式就是 scanf() 和 printf()。 scanf():从标准输入设备(键盘)读取数据,并将值存放在变量中。 printf():将指定的文字/字符串输出到标准输出设备(屏幕)。注意宽度输出和精度输出控制。 除此之外,C语言借助了相应的缓冲区来进行输入和输出。如下图所示: <img src"../../img/image2022080822180366...

STL(standard template libaray标准模板库):是 C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。 原始版本 Alexander Stepanov、Meng Lee 在惠普实验室完成的原始版本,本着开源精神,他们声明允许任何人任意运用、拷贝、修改、传播、商业使用这些代码,无需付费。唯一的条件就是也...

list的文档介绍 1. list 是可以在常数范围内(即 O(1) 时间复杂度)在任意位置进行插入和删除的序列式容器,并且该容器 可以前后双向迭代。 2. list 的底层是 双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。 3. list 与 forwardlist 非常相似:最主要的不同在于 forwardlist 是单链表,只能向后...

我们已经接触过 STL 中的部分容器,比如:vector、list、deque、forwardlist 等,这些容器统称为 序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身。至于 stack 和 queue,他们其实不能算是容器,而应该是容器适配器,是用 deque 封装的。 那什么是关联式容器?它与序列式容器有什么区别? 关联式容器也是用来存储数据的,与序列式容器不同...

我们前面实现了红黑树的插入以及删除(删除有一点bug),因此我们就能用其来实现 map 以及 set,这里只涉及了之前红黑树的插入,因为我们的重点是 map 与 set 是如何同时使用红黑树实现的以及红黑树的迭代器是如何实现的! 一起回忆一下,之前红黑树的参数模板我们是这样子实现的: 有没有发现,我们实现的时候默认用的就是<K, V 结构,也就是 map 的结构,但是 set 呢?重写...

🔍 文档介绍:stack C++ Reference 1. stack 是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行 元素的插入与提取操作。 2. stack 是作为容器适配器实现的,容器适配器即是对特定类封装作为其底层的容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层的,元素特定容器的尾部(即栈顶)被压入和弹出。 3. 标准容器 vect...
string的文档网站 string 是一个管理字符数组的类,要求这个字符数组结尾用 \0 标识 模拟实现涉及的问题如下: 拷贝构造和赋值重载实现 深拷贝 增删查改的相关接口 重载一些常见的运算符如:[] 、 、<< 等 迭代器 对于一个成员函数,什么时候该加 const 呢? 1. 如果是 只读函数 ,则要加 const 2. 如果是 只写函数 ,则不能加...

由哈希表的知识我们可知开散列其实是比闭散列有优势的,所以下面的实现都是基于开散列的基础实现的! 从之前的红黑树改造可知,我们得多传一个 KeyOfT ,因为如果我们的 map 或 set 想存不同的数据类型的话,那么 T 取 Key 的方式就不一样了,比如如果是内置类型则直接取,但是如果是 pair 类型,那我们取的其实是 pair 的 first,所以这里我...

vector的文档介绍 1. vector 是表示可变大小数组的序列容器(动态数组),包含三个迭代器,start 和 finish 之间是已经被使用的空间范围,endofstorage 是整块连续空间(包括备用空间的尾部)。 2. 就像数组一样,vector 也采用的连续存储空间来存储元素。也就是意味着可以采用下标对 vector 的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态...
这个之前我们讲过了,其实本质上就是迭代器的封装!这里就不细讲了,只要注意一点:使用基于范围的 for 循环, 其 for 循环迭代的范围必须是可确定的 C++中的静态断言 staticassert 是一个编译时断言,用于在编译期间检查某个条件是否为真。如果条件为假,则会导致编译错误,否则不会产生任何代码。 静态断言的语法如下: 其中,condition 是一个表达式,如果表达式的...
C++11 的新特性可变参数模板能够让你创建可以接受可变参数的函数模板和类模板,相比 C++98/03,类模版和函数模版中只能含固定数量的模版参数,可变模版参数无疑是一个巨大的改进。 然而由于可变模板参数就比较抽象了,使用起来需要一定的技巧,所以这块还是比较晦涩的。现阶段呢,我们掌握一些基础的可变参数模板特性就够我们用了,所以这里我们点到为止,以后大家如果有需要,再可以深入学习。 ...

传统的C++语法中就有引用的语法,而C++11中新增了的右值引用语法特性,所以从现在开始我们之前学习的引用就叫做左值引用。无论左值引用还是右值引用,都是给对象取别名。 左值是一个表示数据的表达式(如变量名或解引用的指针),我们可以获取它的地址或者可以对它赋值,左值可以出现在 的左边,右值不能出现在 表达式左边。定义时 const 修饰符后的左值,不能给他赋值,但是可以取它的地址。左值引...
在 C++98 中 auto 是一个存储类型的说明符,表明变量是局部自动存储类型,但是局部域中定义局部的变量默认就是自动存储类型,所以 auto 就没什么价值了。 所以 C++11 中废弃 auto 原来的用法,将其用于实现自动类型推导。这样要求必须进行显示初始化,让编译器将定义对象的类型设置为初始化值的类型。 易错点: a...

原来 C++ 类中,有 6 个默认成员函数: 1. 构造函数 2. 析构函数 3. 拷贝构造函数 4. 拷贝赋值重载 5. 取地址重载(了解即可) 6. const 取地址重载(了解即可) 最后重要的是前 4 个,后两个用处不大。默认成员函数就是我们不写编译器会生成一个默认的。 而 C++11 新增了两个:移动构造函数和移动赋值运算符重载。 针对移动构造函数和移动赋值运算符重载有一些需要注意的点如...

我们先来看看下面这段代码: 上述代码中,main 函数中捕获 Func 的异常,而非常关键,因为可能会导致一些内存泄漏的问题,new 会去调用 operator[],而这是有可能会申请失败的,一旦失败就会抛异常被 main 函数捕捉到,那么 Func 下面的 delete 就没有被执行到,这不是妥妥的内存泄漏吗❓❓❓ 这也是异常的引入导致的问题,所以我们必须要解决它,我们可以通过在 F...
在 C++98/03 的泛型编程中,模板实例化有一个很繁琐的地方,就是连续两个右尖括号 会被编译解释成右移操作符,而不是模板参数表的形式,需要一个空格进行分割,以避免发生编译时的错误。 在实例化模板时会出现连续两个右尖括号,同样 staticcast、 dynamiccast、 reinterpretcast、constcast 表达式转换时也会遇到相同的情况。 C++98...

在 C++98 中,标准允许使用花括号 {} 对数组或者结构体元素进行统一的列表初始值设定。比如: 对于一些自定义的类型,却无法使用这样的初始化,比如: 在 c++98 中无法通过编译,导致每次定义 vector 时,都需要先把 vector 定义出来,然后使用循环对其赋初始值,非常不方便。 所以 C++11 扩大了用花括号括起的列表的使用范围,使其可用于所有的内置类型和用户自定义...

闭包有很多种定义, 一种说法是, 闭包是带有上下文的函数。 说白了, 就是有状态的函数,就是有自己的变量。更直接一些, 就是一个类 换了个名字而已。 一个函数, 带上了一个状态, 就变成了闭包了。 那什么叫 “带上状态” 呢? 意思是这个闭包有属于自己的变量, 这些个变量的值是创建闭包的时候设置的, 并在调用闭包的时候, 可以访问这些变量。 函数是代码, 状态是一组变量, ...
拷贝只会发生在两个场景中:拷贝构造函数、赋值运算符重载,因此想要让一个类禁止拷贝,只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。 C++98 的方式: 1. 设置成私有:如果只声明而没有设置成 private,用户自己如果在类外定义了,还是等于可以拷贝 2. 只声明不定义:不定义是因为该函数根本不会调用,定义了其实也没有什么意义,不写反而还简单,而且如果定义了就做不...

该内容中的代码以及解释都是在 vs2022 下的 x86 环境中,涉及的指针都是 4 个字节,如果要在其他的平台下运行,部分代码需要改动。 通俗来说,多态就是不同的类型对象,去做同一件事情的时候会产生不一样的状态。 举个例子:对于买票找个行为,【普通人】去买票可能是【全价】,而【学生】买票可以【半价】,而对于【军人】来说可以【优先购票】。 <im...

1. 终止程序,如 assert,缺陷:用户难以接受。如发生内存错误,除0错误时就会终止程序。 2. 返回错误码,缺陷:需要程序员自己去查找对应的错误。如系统的很多库的接口函数都是通过把错误码放到errno中,表示错误。 3. C 标准库中 setjmp 和 longjmp 组合。这个不是很常用,了解一下。 实际中C语言基本都是使用返回错误码的方式处理错误,部分情况下使用终止程序处理非常严重的错误...

在 C 语言中,如果我们想写多类型的,并且是同一个函数出来的函数,我们只能要几个写几个出来,这样子会显得比较冗余,也加大了程序员的代码量,于是 c++ 中就引入了 函数重载 和 泛型编程 的概念,大大的简化了我们的工作! 仅靠函数重载是完不成泛型编程的需求的,比如说下面的代码: 好像靠函数重载来调用不同类型的 Swap,只是表面上看起来 "通用" 了 ,实际上问题还是没有解决,有新的类...
拷贝只会发生在两个场景中:拷贝构造函数、赋值运算符重载,因此想要让一个类禁止拷贝,只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。 C++98 的方式: 1. 设置成私有:如果只声明而没有设置成 private,用户自己如果在类外定义了,还是等于可以拷贝 2. 只声明不定义:不定义是因为该函数根本不会调用,定义了其实也没有什么意义,不写反而还简单,而且如果定义了就做不...
C++ STL中的空间配置器(Allocator)是一种抽象组件,用于动态分配内存、管理内存池、分配内存、释放内存等操作。空间配置器是 STL 中非常重要的组件,它支持容器的内存分配和释放,同时也可以用于实现其他的内存管理功能。 简单地说就是为各个容器高效的管理空间 (空间的申请与回收) 的,在默默地工作。虽然在常规使用 STL 时,可能用不到它,但站在学习研究的角度,学习它的实...

在 C 语言中,如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与接收返回值类型不一致时,就需要发生类型转化,C 语言中总共有两种形式的类型转换:隐式类型转换、显式类型转换。 1. 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译失败。 2. 显式类型转化:需要用户自己处理。 C语言风格的转换格式很简单,但是有不少缺点的: ...

继承(inheritance)机制是面向对象程序设计,使代码可以复用的最重要的手段。它允许程序员在保持原有类特性的基础上进行扩展,以增加功能。这样产生新的类,称为派生类。 继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。 以前我们接触的复用都是函数复用,而继承是类设计层次的复用。 :bug: 举例: 对于一个学校来说,是有职位与身份的分明的,比如说:校长、数学...