当前位置: 首页 > news >正文

C++ 数组、字符串详解与 C 的差异

一、数组(Array)

在 C++ 中,数组是一种非常基础的数据结构,用于存储连续的同类型元素。尽管 C 和 C++ 在语法上非常接近,但 C++ 对数组有一些增强和特性。


1. 基本数组操作

int example[5];      // 栈上创建一个长度为5的整型数组
example[0] = 2;      // 给第0个元素赋值
std::cout << example[0] << std::endl; // 输出 2
std::cout << example << std::endl;    // 输出数组首地址
  • example 本质上是数组首元素的地址(指针)。

  • example[0] 是整型值。

  • 注意:访问越界(0-4 之外)是未定义行为,Debug 下可能提示内存访问违规,Release 下可能不会报错,但会覆盖无关内存。


2. 数组与循环

数组常常与 for 循环结合:

for(int i=0; i<5; i++)example[i] = i;
  • 小端存储示例:数组连续分配,每个 int 占 4 字节,内存顺序如 00 00 00 00 01 00 00 00 ...

  • example[i] 实际上是 *(example + i),偏移量 = i * sizeof(int)

  • 指针加法按数据类型移动,不是字节。例如:

int* ptr = example;
*(ptr + 2) = 6; // 相当于 example[2] = 6
  • 如果要按字节操作,需要类型转换:

*(int*)((char*)ptr + 2*sizeof(int)) = 6;

3. 栈数组与堆数组

栈数组

int example[5]; // 栈创建
  • 生命周期受作用域控制,离开作用域自动销毁。

  • 内存连续,性能高。

堆数组

int* another = new int[5]; // 堆创建delete[] another; // 需要手动释放
  • 生命周期由程序员控制。

  • 访问可能涉及间接寻址,性能略低。

  • 返回函数中的局部栈数组会失效,堆数组可安全返回:

int* badExample() {int x = 10;return &x; // 不可行,栈变量离开作用域失效
}
  • 静态变量可解决局部变量悬空:

static int x = 10;

4. 类成员数组

栈分配

class Entity {
public:int example[5];Entity() {for(int i=0; i<5; i++)example[i] = i;}
};

堆分配

class Entity {
public:int* example = new int[5];Entity() {for(int i=0; i<5; i++)example[i] = i;}
};
  • 堆数组访问需要间接寻址。

  • 栈数组内存连续,堆数组可能跳跃。


5. 数组大小计算

C 和 C++ 中,数组的大小必须是编译期常量

int size = 5; 
int arr[size]; // ❌ 错误:C++ 不允许,必须是编译期已知常量

因为编译器在编译时就需要知道栈上分配多少空间。
但是 int size = 5; 是运行时变量,编译器没法在编译阶段确定它的值。

int a[5]; int count_a = sizeof(a) / sizeof(int); // 栈数组可计算
  • 对堆数组:

int* b = new int[5]; sizeof(b); // 仅返回指针大小,无法得元素个数
  • C++ 中可使用 conststatic const 原因是:

  • const int exampleSize = 5; 本身就有可能成为编译期常量,但在某些旧的 C++ 标准里,编译器对 const int 的处理不够严格,有时会把它当成运行时常量。

  • static 修饰后,保证它有内部链接性,也就是在编译阶段就能确定值,所以可以用来做数组大小。

static const int exampleSize = 5;//是为了让 exampleSize 在编译期就能确定,从而合法地作为数组长度使用。
int example[exampleSize];

6. C++11 的 std::array

#include <array>
std::array<int, 5> another;
another[0] = 1;
std::cout << another.size() << std::endl; // 获取元素数量
  • std::array 是类模板,提供数组大小和方法。

  • 更安全,比原始数组更易管理。

  • 内部存储仍连续,开销略高。


7. 与 C 的差异总结

特性CC++
基本语法一样一样
栈数组大小计算可以可以,std::array 提供 .size()
堆数组创建与释放malloc/freenew[]/delete[]
构造函数初始化可以在类构造函数中初始化
类型安全与封装高,std::array 支持类型检查
返回数组需要静态或堆数组一样

总结:
C++ 相比 C,数组管理上更灵活:

  1. 提供类成员数组构造与初始化。

  2. 引入 std::array 提供安全接口。

  3. 可以在堆上与栈上自由选择生命周期。

二、字符串(String)

1. C 风格字符串

const char* name = "123";   // 字符串字面量
const char name2[4] = "123"; // 自动添加 '\0'
  • 字符串字面量存储在只读内存,不能修改。

  • 字符串本质是 char 数组,以空终止符 \0 结尾。

  • 未终止的数组打印可能输出随机字符:

const char name2[3] = {'1','2','3'}; // 没有 \0

2. C++ 字符串 std::string


#include <string>
std::string name = "123"; // 构造 std::string 对象
  • 内部封装 char*,提供 .size()+= 等方法。

  • 字符串拼接:

std::string name = "123";
name += "hello"; // 正确
std::string name2 = std::string("123") + "hello"; // 显式转换
  •  C++ 字符串拼接运算对比

    表达式左操作数类型右操作数类型编译器行为结果
    "123" + "hello"const char*const char*指针相加(非法,报错)❌ 错误
    std::string("123") + "hello"std::stringconst char*匹配 operator+(const std::string&, const char*)✅ 结果是 "123hello"
    "123" + std::string("hello")const char*std::string匹配 operator+(const char*, const std::string&)✅ 结果是 "123hello"
    std::string("123") + std::string("hello")std::stringstd::string匹配 operator+(const std::string&, const std::string&)✅ 结果是 "123hello"
    std::string name = "123"; name += "hello";std::stringconst char*匹配 operator+=(const char*)✅ 结果是 "123hello"
    • + 运算要求至少有一个操作数是 std::string,否则两个 const char* 会被当成指针相加。

    • += 更灵活,可以直接接受 const char*

  • C++14 用户自定义字面量:

using namespace std::string_literals;
std::string name = "hello"s + " world";

""s 是一个 后缀字面量,作用是把字符串字面量转换为 std::string

没有 s 的字面量默认是 const char*,不能直接相加。


4. 多行字符串

原始字符串字面量

const char* example = R"(Line1
Line2
Line3)";
std::string example2 = R"(Line1
Line2
Line3)"s;
  • R"( ... )" 表示原始字符串字面量,它会 原样保留换行符和空格,不用写 \n

  • 类型是 const char*(C风格字符串)

  • 在结尾加 s(需要 using namespace std::string_literals;)会把字符串转换成 std::string

  • 类型变成了 std::string,可以方便地使用 .size().find() 等方法。

拼接方式

std::string example = "Line1\n"s"Line2\n"s"Line3\n"s;
  • 相邻字符串字面量会 自动拼接,等效于 "Line1\nLine2\nLine3\n"

  • 每一行的最后我们显式写 \n 来表示换行。

  • s 后缀把每个部分转换成 std::string,这样 + 拼接和字符串方法都能正常使用。


5. 查询与函数传递

bool contains = name.find("lo") != std::string::npos; // 检查是否包含子串
  • name.find("lo") 会返回 "lo" 子串第一次出现的位置(返回类型是 size_t)。

  • 如果没找到,就会返回 std::string::npos(这是一个特殊值,表示“没找到”,其实是 -1 转换为无符号整数)。

void PrintString(const std::string& string) {std::cout << string << std::endl;
}
  • 这里参数写成 const std::string&(常量引用)。

  • 为什么不写 std::string

    • 如果写成 std::string,调用时会复制一份字符串,浪费性能(特别是字符串很长时)。
      如果写成 const std::string&,就不会复制,只是创建一个引用,函数内部直接使用原始字符串。
      const 表示函数不会修改传入的字符串。

void PrintString(std::string s);          // 传值,函数内部有一份拷贝
void PrintString(std::string& s);         // 引用,可以修改原始字符串
void PrintString(const std::string& s);   // 常量引用,只读访问(推荐)

6. 总结

  • C++ 中字符串是 std::string 和 C 风格 char* 的组合。

  • 使用 std::string 更安全、更易管理。

  • 支持 原始字符串、多行字符串。

  • C++ 提供用户自定义字面量,简化字符串拼接。

http://www.dtcms.com/a/407275.html

相关文章:

  • 目前顶尖AI所用算法,包含的数学内容,详细列举
  • 北京网站制作公司有哪些做网站需要多少钱平邑
  • 网站开发环境vs2015是什么郑州博大泌尿外科医院
  • Android 网络 - NetworkCapabilities(NetworkCapabilities 概述、传输类型、网络能力、实例实操)
  • iOS 26 软件性能测试全流程,启动渲染资源压力对比与优化策略
  • 05-vue3+ts中axios的封装
  • 升阳广州做网站公司手游传奇发布网站999
  • 企业备案网站名称怎么填做网站策划需要什么技能
  • 智能体(Agent)的记忆架构:深入解析短期记忆与长期记忆
  • Tongweb708命令行脚本使用指引(by lqw)
  • python学智能算法(三十九)|使用PyTorch模块的normal()函数绘制正态分布函数图
  • wordpress the_content() 截取盐城网站优化推广服务
  • (6) tauri之前端框架性能对比
  • 网站收录查询临沂seo网站建设费入什么科目
  • 做电商网站电商公司wordpress添加标签后哪里显示
  • 优化排名推广技术网站个人网站怎样申请
  • golang面经——context模块
  • Go基础:Go语言能用到的常用时间处理
  • ppt网站超链接怎么做网站报备流程
  • HTTP安全响应头--CSP(Content-Security-Policy)
  • 建筑网站排行榜网站界面设计专利
  • 如何开始第一个开源项目?
  • Moviechat论文阅读
  • 做电影网站算侵权吗上海建设安检站网站
  • 品牌网站模板wordpress判断是否登录
  • 门户网站建设主要内容为什么建设营销型网站
  • 双语版网站引导页常德尚一网
  • Day70 基本情报技术者 单词表05 数据结构
  • 百色高端网站建设网站建设登记表
  • Redis - Hyperloglog类型