C++证道之路第三章字符串、向量和数组

一、命名空间的using声明

在C++中,命名空间是一种将标识符(如变量、函数、类等)组织到一个单独的作用域中的机制。当我们在大型项目中工作时,可能会遇到命名冲突的问题,这时命名空间就非常有用。

然而,在使用命名空间中的成员时,需要在每个成员前加上命名空间的名字,这可能会使代码变得冗长。为了解决这个问题,C++提供了using声明和using指令。

using声明:它用于从命名空间中引入单个标识符。例如:

namespace MyNamespace {void myFunction() { /* ... */ }
}int main() {using MyNamespace::myFunction; // 使用using声明从MyNamespace中引入myFunctionmyFunction(); // 现在可以直接调用myFunction,不需要加上MyNamespace::return 0;
}

 

using指令:它用于从命名空间中引入所有标识符。这通常在头文件中使用,以避免每次使用命名空间中的成员时都必须加上命名空间的名字。但是,如果命名空间很大或包含有命名冲突的标识符,这样做可能会导致问题。

namespace MyNamespace {void myFunction() { /* ... */ }
}int main() {using namespace MyNamespace; // 使用using指令从MyNamespace中引入所有标识符myFunction(); // 现在可以直接调用myFunction,不需要加上MyNamespace::return 0;
}

二、标准库类型string

1定义和初始化string对象

在C++中,std::string 是一个非常强大的字符串处理工具,位于 <string> 标准库中。定义和初始化 std::string 的方式如下:

#include <string>// 默认构造函数
std::string str1;// 基于C风格字符串初始化
const char *cstr = "Hello, World!";
std::string str2(cstr);// 初始化为指定长度和字符
std::string str3(10, 'a'); // "aaaaaaaaaa"// 初始化为另一个string对象的副本
std::string str4(str2);// 初始化为另一个string对象的子串
std::string str5(str2, 7, 5); // "World"
2string对象上的操作

std::string 提供了丰富的操作接口,包括但不限于:

  • 连接

    1std::string str6 = str1 + str2;
  • 比较

    1if (str1 == str2) {
    2    // 相等
    3} else if (str1 < str2) {
    4    // str1小于str2
    5}
  • 查找

    1size_t pos = str1.find("world"); // 查找子串位置
  • 替换

    1str1.replace(pos, 5, "universe");
  • 插入

    1str1.insert(pos, "extra ");
  • 删除

    1str1.erase(pos, 5);
  • 大小

    1size_t len = str1.length();
  • 访问元素

    1char ch = str1.at(pos); // 或者 str1[pos]
3处理string对象中的字符
std::string str = "Hello";
str[0] = 'h'; // 修改第一个字符为小写
char firstChar = str[0]; // 获取第一个字符使用 at() 方法更安全,因为它会在访问越界时抛出异常:、
try {char ch = str.at(10); // 如果str长度小于10,会抛出std::out_of_range异常
} catch (std::out_of_range& e) {std::cerr << "Error: " << e.what() << std::endl;
}

三、标准库类型vector

std::vector 是 C++ 标准模板库 (STL) 中的一个动态数组容器。它可以自动调整其内部存储空间的大小,以便容纳更多的元素。

1定义和初始化vector对象
#include <vector>
#include <iostream>int main() {// 默认构造,创建空的 vectorstd::vector<int> v1;// 构造并初始化为特定大小和值std::vector<int> v2(10, 1); // 创建一个包含10个元素的vector,每个元素值为1// 构造并初始化为另一个vector的副本std::vector<int> v3(v2);// 构造并初始化为一系列初始值std::vector<int> v4{1, 2, 3, 4, 5};// 构造并初始化为迭代器范围内的元素int arr[] = {1, 2, 3, 4, 5};std::vector<int> v5(arr, arr + sizeof(arr) / sizeof(arr[0]));return 0;
}
2向vector对象中添加元素
std::vector<int> v;// 在向量末尾添加元素
v.push_back(10); // 添加整数10// 使用迭代器在向量末尾添加多个元素
std::vector<int> v2{1, 2, 3};
v.insert(v.end(), v2.begin(), v2.end());// 在指定位置插入元素
v.insert(v.begin(), 0); // 在向量开始处插入0// 使用 emplace_back 和 emplace 在运行时直接在向量中构造对象
std::vector<std::string> vs;
vs.emplace_back("Hello"); // 直接在向量中构造字符串对象
3其他vector操作
std::vector<int> v = {1, 2, 3, 4, 5};// 访问元素
int first = v.front(); // 获取第一个元素
int last = v.back(); // 获取最后一个元素// 删除元素
v.pop_back(); // 删除最后一个元素
v.erase(v.begin()); // 删除第一个元素// 清空向量
v.clear();// 检查是否为空
bool empty = v.empty();// 获取大小和容量
size_t size = v.size();
size_t capacity = v.capacity();// 重新分配大小
v.resize(10); // 将向量大小设置为10
v.resize(5, -1); // 将向量大小设置为5,新位置的元素值为-1// 交换两个向量的内容
std::vector<int> v2 = {6, 7, 8};
v.swap(v2);

四、迭代器介绍

迭代器的工作方式类似于指针,但它们被设计成可以与更广泛的容器一起工作,而不仅仅是原始数组。

1使用迭代器
#include <vector>
#include <iostream>int main() {std::vector<int> vec = {1, 2, 3, 4, 5};// 定义迭代器std::vector<int>::iterator it; // 或简写为 auto it
}// 初始化迭代器指向容器的第一个元素
it = vec.begin();// 初始化迭代器指向容器的最后一个元素后的下一个位置
it = vec.end();// 输出容器中的元素
for (it = vec.begin(); it != vec.end(); ++it) {std::cout << *it << " ";
}for (auto &element : vec) {std::cout << element << " ";
}
2迭代器运算

迭代器支持几种运算,这使得它们在遍历容器和执行操作时更加灵活。

it++; // 移动到下一个元素
it--; // 移动到前一个元素if (it1 == it2) {} // 判断两个迭代器是否指向同一位置
if (it1 != it2) {} // 判断两个迭代器是否不指向同一位置int distance = it2 - it1; // 计算it1和it2之间的距离it = it1 + 5; // 移动迭代器5个位置
it = it1 - 2; // 移动迭代器2个位置

五、数组

1定义和初始化内置数组
// 定义一个整型数组,包含5个元素
int arr[5];// 初始化数组
int arr2[5] = {1, 2, 3, 4, 5}; // 显式初始化所有元素
int arr3[5] = {1, 2, 3};       // 隐式初始化剩余元素为0// C++11 及以后版本的初始化语法
int arr4[] = {1, 2, 3, 4, 5};
int arr5[5] = {0};             // 所有元素初始化为0
2访问数组元素
arr[0] = 10; // 设置第一个元素的值
int val = arr[4]; // 获取第五个元素的值
3指针和数组
int arr[5] = {1, 2, 3, 4, 5};
int *ptr = arr; // ptr 现在指向 arr[0]// 通过指针访问元素
std::cout << *ptr << std::endl; // 输出 arr[0]
std::cout << *(ptr + 1) << std::endl; // 输出 arr[1]
4C风格字符串
char str[] = "Hello, World!"; // C风格字符串
std::cout << str << std::endl; // 输出字符串// 访问字符串中的字符
char ch = str[0]; // 获取第一个字符 'H'
5与旧代码的接口
void c_function(char *s) {while (*s) {std::cout << *s++;}
}int main() {char str[] = "Hello from C function";c_function(str); // 调用C风格的函数return 0;
}

 现代C++鼓励使用std::arraystd::vector等更安全、更灵活的容器,因为它们提供了额外的功能并且可以自动管理内存。然而,在某些情况下,使用内置数组和C风格字符串仍然是必要的,尤其是在需要与C库交互或者性能优化要求极高的场景下

六、多维数组

多维数组在内存中是连续存储的,这意味着如果要改变数组的大小,你可能需要重新分配内存,这在C++中通常不是自动的,除非使用std::vectorstd::array等容器。

C++编译器在编译时会检查数组索引是否越界,但在运行时不会,因此你需要确保你的索引值不会超出数组的界限。

多维数组的内存消耗比一维数组大,因为它们通常用于存储大量数据。在资源有限的环境中,应谨慎使用。

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

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

相关文章

使用linux的mail命令发送html格式的邮件

1、关闭本机的sendmail服务或者postfix服务 #执行下面的命令&#xff0c;各位大侠都对号入座吧 #sendmial service sendmail stop chkconfig sendmail off #postfix service postfix stop chkconfig postfix off#再狠一点就直接卸载吧.. yum remove sendmail yum remove postf…

一句话彻底搞懂Java的编译和执行过程

编译和运行可以在不同的计算机上实现。 编译阶段&#xff1a;由Javac编译器将 .Java 的源文件编译为 .class 的字节码文件&#xff1b; 运行阶段&#xff1a; jvm中Java编译器运行 .class 的字节码文件&#xff0c;运行过程中&#xff0c;类加载器从硬盘中找到该字节码文件并…

C语言 | Leetcode C语言题解之第226题翻转二叉树

题目&#xff1a; 题解&#xff1a; struct TreeNode* invertTree(struct TreeNode* root) {if (root NULL) {return NULL;}struct TreeNode* left invertTree(root->left);struct TreeNode* right invertTree(root->right);root->left right;root->right le…

每日Attention学习9——Efficient Channel Attention

模块出处 [CVPR 20] [link] [code] ECA-Net: Efficient Channel Attention for Deep Convolutional Neural Networks 模块名称 Efficient Channel Attention (ECA) 模块作用 通道注意力 模块结构 模块代码 import torch import torch.nn as nn import torch.nn.functional …

快速掌握 ==== js 正则表达式

git 地址 https://gitee.com/childe-jia/reg-test.git 背景 在日常开发中&#xff0c;我们经常会遇到使用正则表达式的场景&#xff0c;比如一些常见的表单校验&#xff0c;会让你匹配用户输入的手机号或者身份信息是否规范&#xff0c;这就可以用正则表达式去匹配。相信大多数…

记一次java进程异常退出原因排查

最近在对一个Java服务进行压测&#xff0c;但是压测一段时间后&#xff0c;java进程就会自动停止&#xff0c;虽然怀疑可能是内存不足原因导致的&#xff0c;但是从服务日志中去看&#xff0c;并没有OOM的相关报错日志。这就很奇怪了&#xff01;然后就从Java启动参数入手&…

【Python基础】代码如何打包成exe可执行文件

本文收录于 《一起学Python趣味编程》专栏&#xff0c;从零基础开始&#xff0c;分享一些Python编程知识&#xff0c;欢迎关注&#xff0c;谢谢&#xff01; 文章目录 一、前言二、安装PyInstaller三、使用PyInstaller打包四、验证打包是否成功五、总结 一、前言 本文介绍如何…

【C语言】continue 关键字详解

当在C语言中使用continue关键字时&#xff0c;它用于控制循环语句的执行流程。与break不同&#xff0c;continue不会终止整个循环&#xff0c;而是终止当前迭代&#xff0c;并立即开始下一次迭代。这种行为使得可以在循环内部根据特定条件跳过某些代码块&#xff0c;从而控制程…

Vue核心 — Vue2响应式原理和核心源码解析(核心中的核心)

一、前置知识 1、Vue 核心概念 Vue 是什么? Vue 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建&#xff0c;并提供了一套声明式的、组件化的编程模型&#xff0c;帮助你高效地开发用户界面。 Vue 核心特点是什么? 响应式数据绑定:…

2024前端面试真题【JS篇】

DOM DOM&#xff1a;文本对象模型&#xff0c;是HTML和XML文档的编程接口。提供了对文档的结构化的表述&#xff0c;并定义可一种方式可以使从程序中对该结构进行访问&#xff0c;从而改变文档的结构、样式和内容。 DOM操作 创建节点&#xff1a;document.createElement()、do…

AI提示词:打造爆款标题生成器

打开GPT输入以下内容&#xff1a; # Role 爆款标题生成器## Profile - author: 姜小尘 - version: 02 - LLM: Kimi - language: 中文 - description: 利用心理学和市场趋势&#xff0c;生成吸引眼球的自媒体文章标题。## Background 一个吸引人的标题是提升文章点击率和传播力…

压缩感知3——重构算法正交匹配追踪算法

算法流程 问题的实质是&#xff1a;AX Y 求解&#xff08;A是M维&#xff0c;Y是N维且N>>M并且稀疏度K<M&#xff09;明显X有无穷多解&#xff0c;重构过程是M次采样得到的采样值升维的过程。OMP算法的具体步骤&#xff1a;(1)用X表示信号&#xff0c;初始化残差e0 …

【普中】基于51单片机的矩阵电子密码锁LCD1602液晶显示 proteus仿真+程序+设计报告+讲解视频

【普中】基于51单片机的矩阵电子密码锁LCD1602液晶显示设计 1.主要功能&#xff1a;讲解视频&#xff1a;2.仿真3. 程序代码4. 设计报告5. 设计资料内容清单&&下载链接资料下载链接&#xff1a; 【普中】基于51单片机的矩阵电子密码锁LCD1602液晶显示设计 ( proteus仿真…

存储产品选型策略 OSS生命周期管理与运维

最近在看阿里云的 云存储通关实践认证训练营这个课程还是不错的。 存储产品选型策略、对象存储OSS入门、基于对象存储OSS快速搭建网盘、 如何做好权限控制、如何做好数据安全、如何做好数据管理、涉及对象存储OSS的权限控制、使用OSS完成静态网站托管、对OSS中存储的数据进行分…

Python不使用元类的ORM实现

不使用元类的简单ORM实现 在 Python 中&#xff0c;ORM&#xff08;Object-Relational Mapping&#xff09;是一种将对象和数据库之间的映射关系进行转换的技术&#xff0c;使得通过面向对象的方式来操作数据库更加方便。通常&#xff0c;我们使用元类&#xff08;metaclass&a…

【Linux】进程(9):进程控制2(进程等待)

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家了解Linux进程&#xff08;9&#xff09;进程控制2&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 目录 一. 为什么要进程等待二. 如何进行进程等待1.wait函数—…

android13 设置左右分屏修改为单屏幕,应用分屏改为单屏

1.前言 android13中,系统设置变成,左边是一级菜单,右侧是二级菜单, 这样跟我们以前android7/8/9的布局是不一样的,我们需要将它修改为一级菜单,点进去才是二级菜单这种。 效果如下 2.系统设置实现分析 它这里使用的是google新出的embedding activity, 相关的知识这里…

Golang | Leetcode Golang题解之第226题翻转二叉树

题目&#xff1a; 题解&#xff1a; func invertTree(root *TreeNode) *TreeNode {if root nil {return nil}left : invertTree(root.Left)right : invertTree(root.Right)root.Left rightroot.Right leftreturn root }

24. 122.买卖股票的最佳时机II,55. 跳跃游戏, 45.跳跃游戏II,1005.K次取反后最大化的数组和

第一天没有利润&#xff0c;至少要第二天才会有利润&#xff0c;所以利润的序列比股票序列少一天&#xff01; 从图中可以发现&#xff0c;其实我们需要收集每天的正利润就可以&#xff0c;收集正利润的区间&#xff0c;就是股票买卖的区间&#xff0c;而我们只需要关注最终利…

在FPGA程序中Handshake(握手)和Register(寄存器)区别

在FPGA程序中&#xff0c;Handshake&#xff08;握手&#xff09;和Register&#xff08;寄存器&#xff09;是两种不同的通信和数据传输机制。它们各有特点和适用场景。以下是它们的区别和应用场景的详细解释&#xff1a; Register&#xff08;寄存器&#xff09; 特点&#…