当前位置: 首页 > 编程笔记 >

C++ 总览

宗鸿博
2023-03-14
本文向大家介绍C++ 总览,包括了C++ 总览的使用技巧和注意事项,需要的朋友参考一下

示例

迭代器就是位置

迭代器是对一系列元素进行导航和操作的一种手段,并且是指针的通用扩展。从概念上讲,重要的是要记住,迭代器是位置,而不是元素。例如,采取以下顺序:

A B C

该序列包含三个元素和四个位置

+---+---+---+---+
| A | B | C |   |
+---+---+---+---+

元素是序列中的事物。位置是可以对序列进行有意义的操作的位置。例如,一个插入到元素A之前之后的位置,而不插入一个元素。删除元素(erase(A))的方法是先找到其位置,然后删除它。

从迭代器到值

为了从位置转换为值,需要取消迭代器的引用

auto my_iterator = my_vector.begin(); // 位置
auto my_value = *my_iterator; // 值

可以将迭代器视为对序列中引用的值的取消引用。这对于理解为什么不应该end()在序列中永远不要取消引用迭代器特别有用:

+---+---+---+---+
| A | B | C |   |
+---+---+---+---+
  ↑           ↑
  |           +-- An iterator here has no value. Do not dereference it!
  +-------------- An iterator here dereferences to the value A.

在C ++标准库中找到的所有序列和容器中,begin()将迭代器返回到第一个位置,并将end()迭代器返回到最后一个位置(而不是最后一个位置!)之后的位置。因此,在这些算法迭代器的名字常常标记first和last:

+---+---+---+---+
| A | B | C |   |
+---+---+---+---+
  ↑           ↑
  |           |
  +- first    +- last

也可以获取任何序列的迭代器,因为即使一个空序列也包含至少一个位置:

+---+
|   |
+---+

在空序列中,begin()并且end()将处于相同位置,并且不能取消引用:

+---+
|   |
+---+
  ↑
  |
  +- empty_sequence.begin()
  |
  +- empty_sequence.end()

迭代器的替代可视化方式是它们标记元素之间的位置:

+---+---+---+
| A | B | C |
+---+---+---+
↑   ^   ^   ↑
|           |
+- first    +- last

取消引用迭代器将返回对该迭代器之后的元素的引用。该视图特别有用的一些情况是:

  • insert 操作会将元素插入迭代器指示的位置,

  • erase 操作将返回一个与迭代器位置相同的迭代器,

  • 一个迭代器及其对应的反向迭代器位于元素之间的同一位置。

无效的迭代器

如果迭代器的位置不再是序列的一部分,则它变为无效(例如,在操作过程中)。在将无效的迭代器重新分配给有效位置之前,无法取消引用。例如:

std::vector<int>::iterator first;
{
    std::vector<int> foo;
    first = foo.begin(); // 首先有效
} // foo超出范围并被销毁
// 此时首先无效

C ++标准库中的许多算法和序列成员函数都有控制迭代器何时无效的规则。每种算法在处理(和使迭代器无效)方式上都不同。

使用迭代器导航

众所周知,迭代器用于导航序列。为此,迭代器必须在整个序列中迁移其位置。迭代器可以按顺序向前推进,而某些可以向后推进:

auto first = my_vector.begin();
++first;                                             // 推进迭代器1的位置
std::advance(first, 1);                              // 推进迭代器1的位置
first = std::next(first);                            // 返回迭代器到下一个元素
std::advance(first, -1);                             // 推进迭代器1的位置 backwards
first = std::next(first, 20);                        // 返回迭代器到元素20的位置
first = std::prev(first, 5);                         // 将迭代器返回到元素5的后退位置
auto dist = std::distance(my_vector.begin(), first); // 返回两个迭代器之间的距离。

请注意,std :: distance的第二个参数应该可以从第一个参数到达(或者换句话说,first应该小于或等于second)。

即使您可以使用迭代器执行算术运算符,也未为所有类型的迭代器定义所有操作。a = b + 3;将适用于随机访问迭代器,但不适用于正向或双向迭代器,仍然可以通过3位将其前进,例如b = a; ++b; ++b; ++b;。因此,建议您在不确定什么是迭代器类型的情况下使用特殊功能(例如,在接受迭代器的模板函数中)。

迭代器概念

C ++标准描述了几种不同的迭代器概念。根据它们在所引用序列中的行为将它们分组。如果您知道迭代器建模的概念(行为类似),则可以确保该迭代器的行为不受其所属的顺序影响。通常按照从最高到最低的顺序来描述它们(因为下一个迭代器概念比其前身要好一步):

  • 输入迭代器:每个位置只能解引用一次。只能前进,一次只能一个位置。

  • 转发迭代器:可以多次取消引用的输入迭代器。

  • 双向迭代器:一种向前迭代器,也可以一次向后移动一个位置。

  • 随机访问迭代器:双向迭代器,一次可以向前或向后移动任意数量的位置。

  • 连续迭代器(自C ++ 17起):一种随机访问迭代器,可确保基础数据在内存中是连续的。

算法可以根据给定的迭代器建模的概念而变化。例如,尽管random_shuffle可以为前向迭代器实现,但是可以提供需要随机访问迭代器的更有效的变体。

迭代器特征

迭代器特征为迭代器的属性提供统一的接口。它们允许您检索值,差,指针,引用类型以及迭代器的类别:

template<class Iter>
Iter find(Iter first, Iter last, typename std::iterator_traits<Iter>::value_type val)  {
    while (first != last) {
        if (*first == val)
            return first;
        ++first;
    }
    return last;
}

迭代器的类别可用于专门化算法:

template<class BidirIt>
void test(BidirIt a, std::bidirectional_iterator_tag)  {
    std::cout << "Bidirectional iterator is used" << std::endl;
}
 
template<class ForwIt>
void test(ForwIt a, std::forward_iterator_tag)  {
    std::cout << "Forward iterator is used" << std::endl;
}
 
template<class Iter>
void test(Iter a)  {
    test(a, typename std::iterator_traits<Iter>::iterator_category());
}

迭代器的类别基本上是迭代器的概念,但连续的迭代器没有自己的标签,因为发现它会破坏代码。

 类似资料:
  • 本文向大家介绍C/C++位操作实例总结,包括了C/C++位操作实例总结的使用技巧和注意事项,需要的朋友参考一下 本文详细叙述了C/C++的位操作,这是C/C++程序设计中非常重要的概念。本文实例对于C/C++初学者来说也具有很好的复习与参考价值。具体分析如下: C/C++对位操作有如下方法: 一、位操作运算符(注意:下面几个运算符不改变原来的变量的值,只是获得运算的结果即一个新值) 按位取反:~

  • 本文向大家介绍C#编程总结(一)序列化总结,包括了C#编程总结(一)序列化总结的使用技巧和注意事项,需要的朋友参考一下 序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据。 几种序列化技术: 1)二进制序列化保持类型保真度,这对于在应用程序的不同调用之间保留对象的状态很有用。例如,通过将对象序列化到剪贴板,可在

  • 本文向大家介绍C++基础知识总结,包括了C++基础知识总结的使用技巧和注意事项,需要的朋友参考一下 不管是自我定位太高,还是职位层次太低,系统复习了一遍很久没有摸过的C++总是有好处的。总结如下: 一、new和malloc的区别 1、new和delete配对,释放数组需要用delete[]。new和delete实际上调用了malloc和free,另外调用了类的构造函数和析构函数。 2、malloc

  • 本文向大家介绍c++ 类和对象总结,包括了c++ 类和对象总结的使用技巧和注意事项,需要的朋友参考一下 话不多说,我们直接进入主题: 对象:客观世界里的一切事物都可以看作是一个对象,每一个对象应当具有属性(静态特征,比如一个班级,一个专业,一个教室)和行为(动态特征,例如:学习,开会,体育比赛等)两个要素。 对象是由一组属性和一组行为构成的。 类(class):就是对象的类型,代表了某一批对象的共

  • 本文向大家介绍C#各类集合汇总,包括了C#各类集合汇总的使用技巧和注意事项,需要的朋友参考一下 集合(Collection)类是专门用于数据存储和检索的类。这些类提供了对栈(stack)、队列(queue)、列表(list)和哈希表(hash table)的支持。大多数集合类实现了相同的接口。 平常在工作中List<T>集合是用的最多的,其次是Array(数组).今天整理一下各类形式的集合,不用就

  • 本文向大家介绍C++ STL库应用汇总,包括了C++ STL库应用汇总的使用技巧和注意事项,需要的朋友参考一下 1、std::max_element的使用 std::min_element类似,求最小 升级可以用到任务队列管理中,通过任务优先级,选择优先级最高的任务 知识点扩展: C++ 的标准模板库(Standard Template Library,STL)是泛型程序设计最成功应用的实例。ST