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

C++数组入门

文章目录

    • 类与结构体中的默认访问控制
    • 数组概述
    • 数组与 `for` 循环的关系
    • 内存布局与指针
    • 动态内存管理
    • 数组指针与地址存储
    • 提前声明数组的大小
      • 代码解释
      • `const int exampleSize = 5;`
      • `static const int exampleSize = 5;`
      • 选择使用哪种方式
    • std::array 创建数组
      • 代码解释
      • 小结

在C++编程中,数组作为一种基本的数据结构,扮演着不可或缺的角色。无论是处理简单的数据存储,还是实现复杂的算法,数组都提供了一种高效且直观的方式来管理和操作数据。对于每一个学习C++的程序员来说,理解数组的原理、使用方法以及它与内存管理的关系,都是迈向更高级编程技巧的重要一步。

在这篇博客中,我们将深入探讨C++数组的各个方面,从基本的定义和初始化,到内存布局与指针的结合使用。通过这些内容,你将不仅能够掌握如何在C++中正确地使用数组,还能理解背后更深层次的内存管理机制。这些知识将帮助你编写更高效、更健壮的C++代码。

类与结构体中的默认访问控制

  • 类 (class) 中的成员变量: 默认情况下,类中的所有成员变量和成员函数的访问控制权限都是 private。这意味着它们只能被类内部的成员函数或者友元函数访问,外部无法直接访问这些成员。

  • 结构体 (struct) 中的成员变量: 默认情况下,结构体中的所有成员变量和成员函数的访问控制权限都是 public。这意味着它们可以被外部直接访问,结构体在这方面与类有着不同的默认行为。

数组概述

  • 数组索引从0开始: 在C++中,数组的索引是从0开始的,这意味着第一个元素的索引是0,第二个元素的索引是1,依此类推。如果数组的大小是 n,那么最后一个元素的索引是 n-1

  • 打印数组: 当你尝试直接打印一个数组时,输出的是数组的首地址(即第一个元素的地址),而不是数组中的元素。数组名本身就是一个指向数组第一个元素的指针,所以打印数组名等价于打印数组的首地址。

在这里插入图片描述

数组与 for 循环的关系

  • 常与 for 循环搭配使用: 数组通常与 for 循环搭配使用,这样可以方便地对数组中的每个元素进行操作。通过循环遍历数组的索引,可以对数组进行初始化、修改或读取。
    在这里插入图片描述

内存布局与指针

  • 连续内存块: 数组在内存中是一块连续的存储空间,每个元素紧邻地存放在一起。这种布局使得数组的访问非常高效,因为通过数组名和索引计算,CPU可以迅速找到对应的内存位置。

  • 指针与数组: 由于数组的内存是连续的,可以很方便地通过指针来操作数组。数组名实际上是一个指向数组第一个元素的指针,因此可以通过指针偏移来访问数组中的任意元素。这种特性使得数组和指针在C++中密不可分,很多低级操作都依赖于此。
    在这里插入图片描述

动态内存管理

  • 使用 new 申请内存: 当需要在运行时动态分配数组时,可以使用 new 运算符。这会在堆(heap)上分配一块连续的内存用于存储数组。由于堆内存的生命周期不受函数调用的限制,因此分配的内存不会在函数结束时自动释放。

  • 释放内存: 动态分配的内存必须由程序员显式释放,使用 delete 运算符来避免内存泄漏。对于数组,需要使用 delete[] 来释放内存,这样可以确保数组的每个元素都得到正确的销毁。
    在这里插入图片描述

数组指针与地址存储

  • 数组指针的赋值: 当创建一个数组并将其赋值给一个指针时,这个指针实际上指向的是数组的首地址,而不是数组中的具体数值。通过这个指针,可以访问数组中的每个元素。由于数组名是一个指向数组第一个元素的指针,所以在需要传递数组时,通常传递的是数组的指针。

  • 在这里插入图片描述

提前声明数组的大小

#include <iostream>class Entity {
public:static const int exampleSize = 5;  // 声明并初始化静态常量int example[exampleSize];          // 使用静态常量声明数组// 构造函数Entity() {for (int i = 0; i < exampleSize; i++) {example[i] = 2;            // 初始化数组元素}}
};int main() {Entity entity;for (int i = 0; i < Entity::exampleSize; i++) {std::cout << entity.example[i] << " ";}return 0;
}

代码解释

  1. 静态常量声明:
    static const int exampleSize = 5; 声明了一个静态常量 exampleSize,它用于定义数组的大小。

  2. 数组声明:
    int example[exampleSize]; 使用 exampleSize 来定义数组的大小。由于 exampleSize 是静态常量,所以在编译时是已知的,可以用来定义数组的大小。

  3. 构造函数:
    构造函数 Entity() 中的循环用来初始化数组 example 中的每一个元素为 2

  4. 打印数组内容:
    main 函数中,我们创建了一个 Entity 对象,并通过循环输出数组 example 的每一个元素。

在类中使用 const int exampleSize = 5static const int exampleSize = 5 都是合法的,但它们的语义和作用范围不同。

const int exampleSize = 5;

  • 非静态成员常量: 如果你只写 const int exampleSize = 5;,这个常量是类的每个实例(对象)都有一份拷贝。这意味着如果你创建多个 Entity 对象,每个对象都持有自己的一份 exampleSize
  • 内存开销: 如果有很多对象实例化,尽管 exampleSize 不变,但每个实例都会有一份拷贝,这可能会稍微增加内存开销(虽然这是微不足道的,除非有大量实例)。
  • 用法限制: 你无法在类外部通过 Entity::exampleSize 直接访问该常量,因为它属于对象的实例。

static const int exampleSize = 5;

  • 静态成员常量: 使用 static const 表明这个常量属于类本身,而不是某个实例。所有的实例共享这一个常量。
  • 内存优化: 由于这个常量是静态的,所有实例共享一份内存,这在有大量实例时可以节省内存。
  • 全局访问: 你可以通过 Entity::exampleSize 直接访问这个常量,而无需创建 Entity 的实例。这在某些情况下会更方便。

选择使用哪种方式

  • 使用 static const: 如果这个常量在所有实例之间不变,且需要被所有实例共享,推荐使用 static const
  • 使用 const: 如果你希望每个实例都有自己独立的常量值,或者这个常量和实例的某些特性强相关,可以使用非静态 const

对于数组大小这种场景,通常会使用 static const,因为数组大小通常是类级别的常量,并不需要每个对象都持有一份拷贝。

std::array 创建数组

#include <iostream>
#include <array>  // 需要包含 <array> 头文件class Entity {
public:static const int exampleSize = 5;  // 声明并初始化静态常量int example[exampleSize];          // 使用静态常量声明数组std::array<int, 5> another;        // 使用 std::array 声明另一个数组// 构造函数Entity() {for (int i = 0; i < another.size(); i++) {example[i] = 2;            // 初始化 example 数组元素another[i] = 2;            // 初始化 another 数组元素}}
};int main() {Entity entity;// 打印 example 数组内容for (int i = 0; i < Entity::exampleSize; i++) {std::cout << entity.example[i] << " ";}std::cout << std::endl;// 打印 another 数组内容for (int i = 0; i < entity.another.size(); i++) {std::cout << entity.another[i] << " ";}return 0;
}

代码解释

  1. 引入 <array> 头文件:
    因为你使用了 std::array,所以必须包含 <array> 头文件。

  2. 静态常量 exampleSize:
    static const int exampleSize = 5; 用来定义数组的大小,同时也在定义 example 数组时使用。

  3. 数组声明:

    • int example[exampleSize]; 是一个普通的C++数组。
    • std::array<int, 5> another; 是一个固定大小为5的标准库数组,具有更丰富的功能和更安全的边界检查。
  4. 构造函数:
    构造函数中使用循环来初始化 exampleanother 数组中的每一个元素为 2。注意这里 another.size() 返回数组的大小,而 exampleSize 也是5,所以两个数组的大小是一致的。

  5. 打印数组内容:
    main 函数中,分别打印了 exampleanother 数组的内容。

小结

通过这种方式,你同时使用了普通C++数组和std::array,其中std::array提供了更多的功能和类型安全。在实践中,如果你需要一个固定大小的数组并且希望有更多的函数支持(如size()),std::array 通常是更好的选择。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Python知识点:如何使用Boto3进行AWS服务管理
  • Electron 集成 Express + p-limit + SQlite WAL读写模式解决并发锁库的问题
  • OpenCV Python 图像处理入门
  • 11.怎么做好一个动态标签页
  • 设计模式21-组合模式
  • P37-数据存储
  • 数据可视化:解锁数据奥秘的钥匙与实战指南
  • 力扣每日一题 特殊数组 II 前缀和
  • 分析 avformat_open_input 数据读取过程
  • 软件需求设计分析报告(Word原件)
  • nginx核心配置示例
  • 基于LangChain手工测试用例转接口自动化测试生成工具!
  • 第七章数据安全10分
  • Excel求和方法之
  • Pytorch如何判断两个模型的权重是否相同(比较权重差异/参数字典)
  • 2018一半小结一波
  • const let
  • IOS评论框不贴底(ios12新bug)
  • Less 日常用法
  • Lsb图片隐写
  • php ci框架整合银盛支付
  • spring学习第二天
  • vue和cordova项目整合打包,并实现vue调用android的相机的demo
  • 动态规划入门(以爬楼梯为例)
  • 简单易用的leetcode开发测试工具(npm)
  • 前端相关框架总和
  • 思维导图—你不知道的JavaScript中卷
  • 用Python写一份独特的元宵节祝福
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • 微龛半导体获数千万Pre-A轮融资,投资方为国中创投 ...
  • ​​​​​​​ubuntu16.04 fastreid训练过程
  • ​io --- 处理流的核心工具​
  • # Swust 12th acm 邀请赛# [ K ] 三角形判定 [题解]
  • #gStore-weekly | gStore最新版本1.0之三角形计数函数的使用
  • #ifdef 的技巧用法
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • (9)YOLO-Pose:使用对象关键点相似性损失增强多人姿态估计的增强版YOLO
  • (八)Flink Join 连接
  • (附源码)springboot电竞专题网站 毕业设计 641314
  • (六)库存超卖案例实战——使用mysql分布式锁解决“超卖”问题
  • (没学懂,待填坑)【动态规划】数位动态规划
  • (每日持续更新)jdk api之FileFilter基础、应用、实战
  • (免费领源码)python+django+mysql线上兼职平台系统83320-计算机毕业设计项目选题推荐
  • (排序详解之 堆排序)
  • (亲测有效)推荐2024最新的免费漫画软件app,无广告,聚合全网资源!
  • (数据结构)顺序表的定义
  • (一)eclipse Dynamic web project 工程目录以及文件路径问题
  • (原创)Stanford Machine Learning (by Andrew NG) --- (week 9) Anomaly DetectionRecommender Systems...
  • *Algs4-1.5.25随机网格的倍率测试-(未读懂题)
  • .net core 实现redis分片_基于 Redis 的分布式任务调度框架 earth-frost
  • .NET Windows:删除文件夹后立即判断,有可能依然存在
  • .NET 中 GetProcess 相关方法的性能
  • .NET/C# 如何获取当前进程的 CPU 和内存占用?如何获取全局 CPU 和内存占用?
  • .NET基础篇——反射的奥妙
  • .Net中的设计模式——Factory Method模式