自学内容网 自学内容网

2024-11-13-C++ 学习:数组和vector+术语表( Primer 第三章)(3)

C++的学习不能断,我感觉冬天了,可以刷一下 C++ primer 这本大厚书。

一、前言

  C++中数组和vector的知识点的学习巩固!string和vector是两种最重要的标准库类型。

二、知识点

2.1 数组初始化vector对象

  不允许使用一个数组为另一个内置类型的数组赋初值,也不允许使用 vector 对象初始化数组。相反的,允许使用数组来初始化 vector 对象。要实现这一目的,只需指明要拷贝区域的首元素地址和尾后地址就可以了:

int int arr[]{012345};/ivec有6个元素,分别是int arr中对应元素的副本
vector<int> ivec(begin(int arr),end(int arr));

在上述代码中,用于创建ivec 的两个指针实际上指明了用来初始化的值在数组 int arr中的位置,其中第二个指针应指向待拷贝区域尾元素的下一位置。此例中,使用标准库函数 begin 和 end来分别计算 int arr 的首指针和尾后指针。在最终的结果中,ivec将包含6个元素,它们的次序和值都与数组int_arr完全一样。

2.2 尽量使用标准库类型而非数组

  使用指针和数组很容易出错。一部分原因是概念上的问题:指针常用于底层操作因此容易引发一些与烦琐细节有关的错误。其他问题则源于语法错误,特别是声明指针时的语法错误。
  现代的 C++程序应当尽量使用 vector 和迭代器,避免使用内置数组和指针;应该尽量使用 string,避免使用C风格的基于数组的字符串

2.3 使用范围 for 语句处理多维数组

   由于在 C++11新标准中新增了范围for语句,所以前一个程序可以简化为如下形式

size t cnt = 0;
for(auto &row : ia) //对于外层数组的每一个元素
for(auto :&col :row)// 对于内层数组的每一个元素
{
col = cnt;//将下一个值赋给该元素
++cnt;//将cnt加1
}

这个循环赋给ia 元素的值和之前那个循环是完全相同的,区别之处是通过使用范围for语句把管理数组索引的任务交给了系统来完成。因为要改变元素的值,所以得把控制变量row和col声明成引用类型。第一个for 循环遍历 ia 的所有元素,这些元素是大小为4的数组,因此row的类型就应该是含有4个整数的数组的引用。第二个for循环遍历那些4元素数组中的某一个,因此co1的类型是整数的引用。每次迭代把cnt的值赋给ia的当前元素,然后将 cnt 加1。
   在上面的例子中,因为要改变数组元素的值,所以我们选用引用类型作为循环控制变量,但其实还有一个深层次的原因促使我们这么做。举一个例子,考虑如下的循环:

for(const auto &row:ia)// 对于外层数组的每一个元素
for(auto col :row)// 对于内层数组的每一个元素
cout << col << endl;

这个循环中并没有任何写操作,可是我们还是将外层循环的控制变量声明成了引用类型,这是为了避免数组被自动转成指针。假设不用引用类型,则环如下述形式:

for (auto row : ia) // 不对的!!!!!!
for(auto col :row)

程序将无法通过编译。这是因为,像之前一样第一个循环遍历ia的所有元素,注意这些元素实际上是大小为4的数组。因为row不是引用类型,所以编译器初始化row时会自动将这些数组形式的元素(和其他类型的数组一样)转换成指向该数组内首元素的指针。 这样得到的 row 的类型就是 int*,显然内层的循环就不合法了,编译器将试图在一个int*内遍历,这显然和程序的初衷相去甚远。
  要使用范围 for 语句处理多维数组,除了最内层的循环外,其他所有循环的控制变量都应该是引用类型。

2.4 指针和多维数组

  使用标准库函数begin和 end也能实现同样的功而且看起来更简洁一些:

// p指向 ia 的第一个数组
for(auto p=begin(ia);p!=end(ia);++p)
{// q指向内层数组的首元素
for(auto q=begin(*p);q!=end(*p);++q)
cout << *q<<'';// 输出q所指的整数值
cout << endl;
}

2.6 术语表

  • begin 是string和vector 的成员,返回指向第一个元素的迭代器。也是一个标准库函数,输入一个数组,返回指向该数组首元素的指针。
  • 缓冲区溢出(buffer overflow) 一种严重的程序故障,主要的原因是试图通过一个越界的索引访问容器内容,容器类型包括string、vector和数组等。
  • C风格字符串(C-style string) 以空字符结束的字符数组。字符串字面值是C风格字符串,C风格字符串容易出错。
  • 类模板(class template) 用于创建具体类类型的模板。要想使用类模板,必须提供关于类型的辅助信息。例如,要定义一个vector对象需要指定元素的类型:vector包含 int 类型的元素。
  • 编译器扩展(compiler extension) 某个特定的编译器为C++语言额外增加的特性。基于编译器扩展编写的程序不易移植到其他编译器上。
  • 容器(container) 是一种类型,其对象容纳了一组给定类型的对象。vector是种容器类型。
  • 拷贝初始化(copy initialization) 使用赋值号(=)的初始化形式。新创建的对象是初始值的一个副本。
  • difference_type 由string 和vector 定义的一种带符号整数类型,表示两个迭代器之间的距离。
  • 直接初始化(direct initialization) 不使用赋值号(=)的初始化形式。
  • empty 是string和vector的成员,返回一个布尔值。当对象的大小为0时返回真,否则返回假。
  • end 是string和vector的成员,返回一个尾后迭代器。也是一个标准库函数,输入一个数组,返回指向该数组尾元素的下一位置的指针。
  • getline 在string头文件中定义的一个函数,以一个istream对象和一个string对象为输入参数。该函数首先读取输入流的内容直到遇到换行符停止,然后将读入的数据存入 string对象,最后返回istream对象。其中换行符读入但是不保留。
  • 索引(index) 是下标运算符使用的值。表示要在 string对象、vector 对象或者数组中访问的一个位置。
  • 实例化(instantiation) 编译器生成一个指定的模板类或函数的过程。
  • 迭代器(iterator) 是一种类型,用于访问容器中的元素或者在元素之间移动。
  • 迭代器运算(iterator arithmetic) 是string或vector的迭代器的运算:迭代器与整数相加或相减得到一个新的迭代器,与原来的迭代器相比,新迭代器向前或向后移动了若干个位置。两个迭代器相减得到它们之间的距离,此时它们必须指向同一个容器的元素或该容器尾元素的下位置。
  • 以空字符结束的字符串(null-terminated string) 是一个字符串,它的最后一个字符后面还跟着一个空字符(‘\0’)。
  • 尾后迭代器(off-the-end iterator) end函数返回的迭代器,指向一个并不存在的元素,该元素位于容器尾元素的下一位置。
  • 指针运算(pointer arithmetic) 是指针类型支持的算术运算。指向数组的指针所支持的运算种类与迭代器运算一样。
  • prtdifft 是cstddef头文件中定义的一种与机器实现有关的带符号整数类型,它的空间足够大,能够表示数组中任意两个指针之间的距离。
  • push_back 是vector的成员,向vector对象的末尾添加元素。
  • 范围 for 语句(range for) 一种控制语句,可以在值的一个特定集合内迭代。
  • size 是string和vector的成员,分别返回字符的数量或元素的数量。返回值的类型是size type.
  • size_t 是cstddef 头文件中定义的一种与机器实现有关的无符号整数类型,它的空间足够大,能够表示任意数组的大小。
  • size_type 是string 和 vector 定义的类型的名字,能存放下任意string对象或vector 对象的大小。在标准库中,size_type 被定义为无符号类型。
  • string 是一种标准库类型,表示字符的序列。
  • using声明(using declaration) 令命名空间中的某个名字可被程序直接使用。
    using 命名空间::名字;
    上述语句的作用是令程序可以直接使用名字,而无须写它的前缀部分命名空间::
  • 值初始化(valueinitialization) 是一种初始化过程。内置类型初始化为0,类类型由类的默认构造函数初始化。只有当类包含默认构造函数时,该类的对象才会被值始化。对于容器的初始化来说,如果具明了容器的大小而没有指定初始值的话就会执行值初始化。此时编译器会生成个值,而容器的元素被初始化为该值。
  • vector 是一种标准库类型,容纳某指定类型的一组元素
  • ++运算符(++ operator) 是迭代器和指针定义的递增运算符。执行“加1”操作使得迭代器指向下一个元素。
  • [运算符([]operator) 下标运算符。obj[j]得到容器对象obj中位置j的那个元素。索引从0开始,第一个元素的索引是0,尾元素的索引是obj.size()-1。下标运算符的返回值是一个对象。如果p是指针、n是整数,则p[n]与*(p+n)等价。
  • ->运算符(->operator) 箭头运算符,该运算符综合了解引用操作和点操作。a->b等价于(*a) .b。
  • <<运算符(<<operator) 标准库类型 string定义的输出运算符,负责输出string对象中的字符。
  • >>运算符(>>operator) 标准库类型string 定义的输入运算符,负责读入一组字符,遇到空白停止,读入的内容赋给运算符右侧的运算对象,该运算对象应该是一个 string 对象。
  • !运算符(!operator) 逻辑非运算符,将它的运算对象的布尔值取反。如果运算对象是假,则结果为真,如果运算对象是真,则结果为假。
  • &&运算符(&&operator) 逻辑与运算符如果两个运算对象都是真,结果为真。只有当左侧运算对象为真时才会检查右侧运算对象。
  • || 运算符(|| operator) 逻辑或运算符,任何一个运算对象是真,结果就为真。只有当左侧运算对象为假时才会检查右侧运算对象。

总结

  • 多学习,多总结,温故而知新,加油~

在这里插入图片描述

代码是在 visual studio 中编写的,该软件还是比较好用的,我安装的是2022专业版;

共勉!


原文地址:https://blog.csdn.net/weixin_42269028/article/details/143726578

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!