《C++ Primer》第3章 字符串、向量和数组(三)

news2024/11/25 9:41:48

参考资料:

  • 《C++ Primer》第5版
  • 《C++ Primer 习题集》第5版

3.5 数组(P101)

数组类似于 vector ,不同点在于数组的大小固定不变,在某些情况下性能较好,但灵活性较差。

3.5.1 定义和初始化内置数组(P101)

数组是一种复合类型,声明形如 a[d] ,其中 d 是数组的维度。维度必须大于 0 且必须是一个常量表达式。默认情况下,数组的元素被默认初始化

如果在函数内部定义了内置类型的数组,则默认初始化会令数组含有未定义的值。

定义数组时必须指定数组类型,不允许通过 auto 推断元素类型。不存在引用的数组。

显式初始化数组元素

可以对数组进行列表初始化,此时可以忽略数组的维度:

  • 如果声明数组时没有指明维度,编译器会根据初始值的数量计算出维度。
  • 如果指明了维度,那么初始值的数量不能超过维度,如果初始值的数量小于维度,则剩下的元素被初始化为默认值

内置类型的默认值为 0 ,类类型执行类的默认初始化。

字符数组的特殊性

可以使用字符串字面值对字符数组进行初始化,此时需要留意字符串字面值结尾的空字符 '\0'

不允许拷贝和赋值

不能将数组的内容拷贝给其他数组作初始值;不能用数组为其他数组赋值:

int a[] = {0 ,1, 2};
int a1[] = a;    // 错误
a1 = a;    // 错误

理解复杂的数组声明

默认情况下,修饰符由内向外由右向左依次绑定:

int *ptrs[10];    // 含有10个int*的数组

// 指向含有10个int元素的数组的指针
int (*Parray)[10] = &arr;
// 这里遇到一个问题,&arr会被编译器识别成int (*)[10]类型,而arr会被编译器识别成int *类型

3.5.2 访问数组元素(P103)

数组的元素可以用范围 for 语句或下标运算符进行访问。使用数组下标时,通常将其定义为 size_t 类型。size_t 是与机器相关的无符号类型,定义在 cstddef 头文件中。

后面会提到,下标运算符可以接受负数,所以这里是“通常”使用 size_t

数组使用的下标运算符是由 C++ 语言直接定义的,可以用于任何数组类型。

检查下标的值

下标大于 0 而小于数组大小。

3.5.3 指针和数组(P105)

在很多用到数组名字的地方,编译器会自动将其替换为一个指向数组首元素的指针

string nums[] = {"one", "two", "three"};
string *p = nums;    // 等价于p = &nums[0]

使用 decltype 关键字时,上述转换不会发生;使用 sizeof 运算符时,数组名代表整个数组;使用 &数组名 时,得到的是指向整个数组的指针

指针也是迭代器

vector 迭代器支持的运算,指向数组元素的指针全部支持。

标准库函数beginend

C++11 新标准引入了 beginend 函数,参数均为数组:

int ia[] = {0, 1, 2, 3, 4};
int *b = begin(ia), *e = end(id);

指针运算

两个指针相减的类型为 ptrdiff_t ,是定义在 cstddef 中的机器相关的有符号类型

指针的比较同样适用于空指针和所指对象非数组的指针。

解引用和指针运算的交互

int ia[] = {0, 1, 2, 3, 4};
int last = *(ia+4);

下标和指针

对数组执行下标运算实质上是对指向数组元素的指针执行下标运算:

int i = ia[2];

int *p = ia;
i = *(p+2);

内置的下标运算可以处理负值;标准库类型的下标运算使用的下标必须为无符号数( ::size_type ),不能处理负值。

3.5.4 C风格字符串(P109)

尽量不要使用 C 风格字符串,因为其容易引发安全漏洞。

字符串字面值是 C 风格字符串的实例。C 风格字符串是一种约定俗成的写法,把字符串存放在字符数组中,并以空字符结尾。

C标准库string函数

image-20230914144656327

上述函数定义在 cstring 头文件中,函数的参数均为指向以空字符结尾的字符数组的指针,但函数本身并不负责验证这一点。所以如果传入一个不以空字符结尾的字符数组的指针,可能会发生错误。

比较字符串

目标字符串的大小由调用者决定

在执行 C 风格字符串的拼接和复制操作时,必须保证目标字符串有足够的空间。

3.5.4 与旧代码的接口(P111)

混用string对象和C风格字符串

任何出现字符串字面值的地方,都可以用以空字符结尾的字符数组来替代:

  • 允许使用以空字符结尾的字符数组为 string 对象初始化或赋值。
  • string 的加法运算中允许其中一个运算对象为以空字符结尾的字符数组。

如果想用 string 对象初始化一个字符数组,可以使用 string 类中的 c_str 函数:

string s("hello");
const char *str(s);    // 错误
const char *str(s.c_str());    // 正确,但不推荐

c_str 函数的返回值类型是 const char* ,指向一个以空字符结尾的字符数组,该数组所存的内容恰好与 string 对象中的内容一致。需要注意的是,c_str 返回的数组可能会因为其 string 对象的改动而失效,所以最好在执行 c_str 后对字符数组进行拷贝:

char *str = new char[20];
strcpy(str, s.c_str);

使用数组初始化 vector 对象

允许用数组初始化 vector 对象,需要给出数组的首元素地址和尾后地址:

int ia[] = {0, 1, 2, 3, 4};
vector<int> iv(begin(ia), end(ia));
vector<int> iv1(ia, ia+1);    // 使用数组中的部分元素初始化vector

现代 C++ 程序应尽量使用 vectorstring 和迭代器,而避免使用数组、C 风格字符串和指针。

3.6 多维数组(P112)

严格来说,C++ 没有多维数组,只有数组的数组:

int ia[3][4];    // ia为维度为3的数组,其中的元素是维度为4的int数组

多维数组的初始化

下面的两种写法是等价的:

int ia[2][2] = {
    {0, 1},
    {2, 3}
};
int ia[2][2] = {0, 1, 2, 3};

在列表初始化多维数组时,不必列出所有元素,未列出的元素执行默认值初始化。下面两种写法的含义不同:

int ia[2][2] = {
    {0}, 
    {1}
};
int ia[2][2] = {0, 1}

多维数组下标的引用

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

int ia[3][4] = {};
for(const auto &row : ia){
    for(auto column : row){
        cout << col << endl;
    }
}

注意,外层循环的控制变量必须声明成引用类型,否则控制变量将被设置为指针类型

指针和多维数组

多维数组实际上数组的数组,所以数组名转换得来的指针指向第一个内层数组:

int ia[3][4] = {};
int (*p)[4] = ia;

使用 autodecltype 可以避免复杂的数组指针:

for(auto p=begin(ia);p!=end(ia);p++){
    for(auto q=begin(*p);q!=end(*p);q++){
        cout << *q << endl;
    }
}

类型别名简化多维数组指针

using int_array int[4];
int_array *p = ia;

cltype` 可以避免复杂的数组指针:

for(auto p=begin(ia);p!=end(ia);p++){
    for(auto q=begin(*p);q!=end(*p);q++){
        cout << *q << endl;
    }
}

类型别名简化多维数组指针

using int_array int[4];
int_array *p = ia;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1009562.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一文了解袋鼠云在实时数据湖上的探索与实践

近日&#xff0c;袋鼠云大数据引擎专家郝卫亮&#xff0c;为大家带来了《袋鼠云在实时数据湖上的探索与实践》主题分享&#xff0c;帮助大家能了解到什么是实时数据湖、如何进行数据湖选型及数据平台建设数据湖的经验。 如今&#xff0c;大规模、高时效、智能化数据处理已是“…

阿里云新用户:定义,专享福利及优惠活动

随着云计算技术的快速发展&#xff0c;越来越多的个人与企业开始将业务迁移到云端。阿里云作为国内领先的云计算服务提供商&#xff0c;为新用户提供了一系列专享福利和优惠活动。本文将详细介绍阿里云新用户的定义、专享福利和优惠活动&#xff0c;助力大家轻松上云&#xff0…

OPCAE接口

目录 1 主要接口 1.1 OPCEventServer对象 1.2 OPCEventSubscription对象 1.3 OPCEventAreaBrowser对象&#xff08;可选&#xff09; 1.4 自定义接口开发注意 2 OPCEventServer 2.1 接口介绍 2.2 接口方法 3 IOPCEventServer2 3.1 接口介绍 3.2 接口方法 4 IConnect…

堆排序(Topk问题)

1.堆排序 堆排序是在堆的思想上面进行延伸的一种排序方法,原理就是利用堆的特性. 堆排序首先得建堆,这里建堆有一个原则: 升序建大堆降序建小堆 利用堆删除的思想来进行排序: 建堆和堆删除都可以使用向下调整的方法来实现 堆删除的向下调整和建堆的向上调整在堆的实现这篇博…

快速搭建超轻量级图床——Cpolar+和树洞外链

文章目录 1.前言2. 树洞外链网站搭建2.1. 树洞外链下载和安装2.2 树洞外链网页测试2.3 cpolar的安装和注册 3.本地网页发布3.1 Cpolar临时数据隧道3.2 Cpolar稳定隧道&#xff08;云端设置&#xff09;3.3 Cpolar稳定隧道&#xff08;本地设置&#xff09; 4.公网访问测试5.结语…

MT6785(Helio G95)安卓核心板_联发科4G高能低耗安卓主板开发板

MTK6785&#xff08;Helio G95&#xff09;安卓核心板采用八核 CPU 具有两个强大的 Arm Cortex-A76 处理器内核&#xff0c;主频高达 2.05GHz&#xff0c;外加六个 Cortex-A55 高效处理器。其强大的图形性能由 Arm Mali-G76 MC4 提供&#xff0c;速度可提升至 900MHz 。高达 10…

【高效开发工具系列】Fork版本管理

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

CUDA小白 - NPP(9) 图像处理 Statistical Operations

cuda小白 原始API链接 NPP GPU架构近些年也有不少的变化&#xff0c;具体的可以参考别的博主的介绍&#xff0c;都比较详细。还有一些cuda中的专有名词的含义&#xff0c;可以参考《详解CUDA的Context、Stream、Warp、SM、SP、Kernel、Block、Grid》 常见的NppStatus&#xf…

游戏平台能否进行定制开发?

游戏平台通常可以进行定制开发&#xff0c;以满足游戏开发商或发行商的特定需求。定制开发可以确保平台更好地适应特定游戏的要求和运营策略。以下是一些常见的定制开发方面&#xff1a; 用户界面和外观&#xff1a;定制平台的用户界面和外观&#xff0c;以符合游戏公司和游戏本…

冒泡排序及其优化

前言 本文将简单介绍冒泡排序及其优化版本&#xff0c;默认从小到大顺序 什么是冒泡排序 冒泡排序是一种简单且经典的排序算法。 基本思想&#xff1a; 是通过反复交换相邻的未按顺序排列的元素&#xff0c;将最小&#xff08;或最大&#xff09;的元素逐渐“浮”到正确位置…

MongoDB差异数据对比的快速指南

MongoDB是一种非关系型数据库&#xff0c;它以灵活的 JSON-like 文档的形式存储数据&#xff0c;这种特性使其在处理大量数据和实现快速开发时更具有优势。而由于其灵活的数据模型和强大的性能&#xff0c;MongoDB 被广泛应用在各种业务场景中。随着业务的发展和数据的增长&…

浅谈STL|STL函数对象篇

一.函数对象概念 概念: 重载函数调用操作符的类&#xff0c;其对象常称为函数对象 函数对象使用重载的()时&#xff0c;行为类似函数调用&#xff0c;也叫仿函数 本质: 函数对象(仿函数)是一个类&#xff0c;不是一个函数 特点 函数对象在使用时&#xff0c;可以像普通函数那…

【RocketMQ】消息的拉取

在上一讲中&#xff0c;介绍了消息的存储&#xff0c;生产者向Broker发送消息之后&#xff0c;数据会写入到CommitLog中&#xff0c;这一讲&#xff0c;就来看一下消费者是如何从Broker拉取消息的。 RocketMQ消息的消费以组为单位&#xff0c;有两种消费模式&#xff1a; 广播…

C语言——三子棋游戏

本文目录 三子棋游戏简介三子棋游戏功能说明游戏界面 C语言代码实现多个文件共同实现game.hgame.ctest.c 三子棋游戏实现逻辑分析编写test.c 文件实现menu()函数实现game()函数打印空棋盘选手落子判断输赢实现game()函数 源代码game.hgame.ctest.c 更多C语言实战项目&#xff0…

微信会员卡开发流程

功能需求&#xff1a; 通过微信第三方平台创建的模板小程序&#xff0c;想要实现用户在小程序支付一定金额后领取会员卡&#xff0c;领取会员卡后可给用户下发一定数量的优惠券&#xff0c;并且实现用户在小程序消费享受商品折扣。 开发流程&#xff1a; 一、了解微信的3个平…

AMS爆炸来袭,上线即巅峰

1.关于首发项目Antmons(AMS)空投结果 Gate.io Startup 首发项目Antmons代币AMS于Aug15th,AM 07:00开始下单&#xff0c;24小时内下单同等对待总共有15,950人下单&#xff0c;下单总价值超过1,000万美金分发系数约为0.001640495298341。根据上线规则AMS项目认购成功&#xff0c;…

67、数据源配置 及 配置多个数据源--C3P0 数据源 和 Hikari 数据源

★ Spring Boot如何选择DataSource数据源 优先级从高到低&#xff1a; HikariCP > Tomcat pooling DataSource > Commons DBCP2 如果要使用Tomcat pooling DataSource这种池化数据源&#xff0c; 那么可以用</exclusions>这个把HikariCP 排除掉&#xff0c;然后sp…

前端html原生页面兼容多端H5和移动端适配方案

目录 图片代码最后 图片 是一个注册页面 代码 自己查看效果 注意: 单位全部用rem这样才能保证兼容性适配多端&#xff0c;px转rem转换公式 1px 1/37.5rem 所以想要20px应该对应20/37.5 0.53rem <!DOCTYPE html> <html lang"en"><head><met…

生成随机数列向量并保存到不同的log文件中

随机数列要求 长度 10元素随机每个数列中有两个相同的元素生成到100个文本中每个文本数列数量为 1000 代码 import torch import pickle import numpy as np import os import shutil import loggingdef creat_logger(log_path,logging_name,suf_name):if not os.path.exists(…

免费知识管理系统,让企业管理文档数据更便捷

编者按&#xff1a;本文详细介绍了免费强大的低代码平台在构建知识管理系统方面的优势&#xff0c;并介绍了其知识管理系统独特的功能。只需轻松操作&#xff0c;即可体验到该平台带来的便捷与高效&#xff01;快来了解如何利用这一神奇的工具&#xff0c;让知识管理变得更加轻…