高程 | 数组、指针与字符串(c++)

2024-02-15 17:28

本文主要是介绍高程 | 数组、指针与字符串(c++),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 📚数组
    • 🐇数组的概念
    • 🐇数组的声明与使用
    • 🐇数组的存储与初始化
    • 🐇数组作为函数参数
    • 🐇对象数组
  • 📚指针
    • 🐇内存空间的访问方式
    • 🐇指针变量的声明
    • 🐇指针运算
    • 🐇指针的赋值
    • 🐇指向常量的指针
    • 🐇指针类型的常量
    • 🐇用指针处理数组元素
    • 🐇指针数组
    • 🐇用指针作为函数参数
    • 🐇指针类型的函数
    • 🐇指向函数的指针
    • 🐇对象指针
  • 📚动态内存分配
    • 🐇必要性
    • 🐇new和delete
    • 🐇动态创建多维数组
  • 📚用vector创建数组对象
  • 📚深拷贝与浅拷贝
  • 📚字符串

📚数组

🐇数组的概念

  • 数组是具有一定顺序关系的若干相同类型变量的集合体,组成数组的变量称为该数组的元素。
  • 数组属于构造类型。

🐇数组的声明与使用

  • 声明
    在这里插入图片描述
  • 使用
    • 数组元素必须先声明,后使用。
    • 只能逐个引用数组元素,而不能一次引用整个数组。例如:a[0]=a[5]+a[7]-a[2*3]b[1][2]=a[2][3]/2
    • 下标值不得超过声明时所确定的上下界。

🐇数组的存储与初始化

  • 🥕一维数组
    • 一维数组的存储:数组元素在内存中顺次存放,它们的地址是连续的。
      在这里插入图片描述
    • 一维数组的初始化:可以在定义数组的同时赋给初值。
      在这里插入图片描述
  • 🥕二维数组
    • 二维数组的存储
      在这里插入图片描述
    • 二维数组的初始化
      在这里插入图片描述

🐇数组作为函数参数

  • 数组元素作实参,与单个变量一样。
  • 数组名作参数,形、实参数都应是数组名(实质上是地址)。
  • 类型要一样,传送的是数组首地址。对形参数组的改变会直接影响到实参数组。

🐇对象数组

  • 声明:类名 数组名[元素个数];
  • 访问:数组名[下标].成员名
  • 初始化:数组中每一个元素对象被创建时,系统都会调用类构造函数初始化该对象。
    • 通过初始化列表赋值。例:Point a[2]={Point(1,2),Point(3,4)};
    • 如果没有为数组元素指定显式初始值,数组元素便使用默认值初始化(调用缺省构造函数)。
  • 数组元素所属类的构造函数
    • 不声明构造函数,则采用缺省构造函数。
    • 各元素对象的初值要求为相同的值时,可以声明具有默认形参值的构造函数。
    • 各元素对象的初值要求为不同的值时,需要声明带形参的构造函数。
    • 当数组中每一个对象被删除时,系统都要调用一次析构函数。

📚指针

  • C语言指针详解,30分钟玩转C语言指针
  • 【动画教程】C语言指针动画演示

🐇内存空间的访问方式

  • 通过变量名访问
  • 通过地址访问

🐇指针变量的声明

  • 概念
    在这里插入图片描述
    • 指针:内存地址,用于间接访问内存单元。
    • 指针变量:用于存放地址的变量。

🐇指针运算

  • *称为指针运算符,是一个一元操作符,表示指针所指向的对象的值
  • &称为取地址运算符,也是一个一元操作符,是用来得到一个对象的地址
  • 指针变量的运算
    • 指针变量的算术运算
      在这里插入图片描述

      • 这种运算的结果取决于指针指向的数据类型
        在这里插入图片描述
    • 指针变量的关系运算&赋值运算
      在这里插入图片描述

🐇指针的赋值

  • 指针变量的初始化
    在这里插入图片描述
    • 注意事项
      • 用变量地址作为初值时,该变量必须在指针初始化之前已声明过,且变量类型应与指针类型一致。
      • 可以用一个已赋初值的指针去初始化另一个指针变量。
      • 不要用一个内部 auto 变量去初始化 static 指针。@野指针详解
  • 指针变量的赋值运算
    • 指针名 = 地址
      • “地址”中存放的数据类型与指针类型必须相符。
      • 向指针变量赋的值必须是地址常量或变量,不能是普通整数。但可以赋值为整数0,表示空指针。
      • 指针的类型是它所指向变量的类型,而不是指针本身数据值的类型,任何一个指针本身的数据值都是unsigned long int型。
      • 允许声明指向 void 类型的指针。该指针可以被赋予任何类型对象的地址。例: void *general; ,不能声明void类型的变量。

🐇指向常量的指针

  • 不能通过指针来改变所指对象的值,但指针本身可以改变,可以指向另外的对象。
    在这里插入图片描述

🐇指针类型的常量

  • 若声明指针常量,则指针本身的值不能被改变。
    在这里插入图片描述

  • const int * p1 int * const p2区别是什么
    • const int * p1 声明了一个指向整型常量的指针p1,因此不能通过指针p1来改变它所指向的整型值;
    • int * const p2声明了一个指针型常量,用于存放整型变量的地址,这个指针一旦初始化后,就不能被重新赋值了。

  • 定义一个整型变量a,一个整型指针p,一个引用r,通过p把a的值改为10,通过r把a的值改为5
    void main()
    {int a;int *p = &a;int &r = a;*p = 10;r = 5;
    }
    

🐇用指针处理数组元素

  • 声明与赋值
    • int a[10], *pa; pa=&a[0]; pa=a;
    • 经过上述声明及赋值后:
      • pa就是a[0](pa+1)就是a[1],… ,*(pa+i)就是a[i]
      • a[i], *(pa+i), *(a+i), pa[i]都是等效的。
      • 不能写 a++,因为a是数组首地址是常量。

🐇指针数组

  • 数组的元素是指针型
    在这里插入图片描述
  • 指针数组VS二维数组
    在这里插入图片描述
    在这里插入图片描述

🐇用指针作为函数参数

  • 以地址方式传递数据,可以用来返回函数处理结果。
  • 实参是数组名时形参可以是指针。
  • 指向常量的指针做形参(不通过指针改变指针所指向对象的内容)
    #include<iostream>using namespace std;const int N = 6;void print(const int *p, int n);int main() 
    {int array[N]; for (int i = 0; i < N; i++)    cin>>array[i];  print(array, N);  return 0;}void print(const int *p, int n) {  cout << "{ " << *p;  for (int i = 1; i < n; i++)     cout << ", " << *(p+i);  cout << " }" << endl;}
    

🐇指针类型的函数

  • 函数的返回值是地址,该函数就是指针类型的函数。
  • 声明形式:存储类型 数据类型 *函数名()
  • 注意
    • 不要将非静态局部地址用作函数的返回值。
    • 返回的指针要确保在主调函数中是有效、合法的地址。
      • 例1:主函数中定义的数组,在子函数中对该数组元素进行某种操作后,返回其中一个元素的地址,这就是合法有效的地址
      • 例2:在子函数中定义局部变量后将其地址返回给主函数,就是非法地址
      • 例3:在子函数中通过动态内存分配new操作取得的内存地址返回给主函数是合法有效的,但是内存分配和释放不在同一级别,要注意不能忘记释放,避免内存泄漏

🐇指向函数的指针

  • 声明形式:存储类型 数据类型 (*函数指针名)();
  • 函数指针指向的是程序代码存储区。
  • 典型用途——实现函数回调通过函数指针调用函数。
    • 例如将函数的指针作为参数传递给一个函数,使得在处理相似事件的时候可以灵活的使用不同的方法。
    • 调用者不关心谁是被调用者。它只需知道存在一个具有特定原型和限制条件的被调用函数。与函数名具有相同的作用。

🐇对象指针

  • 声明形式:类名 *对象指针名;
  • 通过指针访问对象成员:对象指针名->成员名ptr->getx()相当于(*ptr).getx();
  • this指针
    • 隐含于每一个类的成员函数中的特殊指针。
    • 明确地指出了成员函数当前所操作的数据所属的对象。
      • 当通过一个对象调用成员函数时,系统先将该对象的地址赋给this指针,然后调用成员函数,成员函数对对象的数据成员进行操作时,就隐含使用了this指针。
  • C++类和对象的使用之对象指针

📚动态内存分配

  • 动态内存分配 (详解版)

🐇必要性

  • 数组可以对大量的数据和对象进行有效管理,但很多情况下,程序运行之前并不能确切知道数组中元素的个数。
  • 动态内存分配技术:保证程序在运行过程中按实际需要申请适量内存,且在使用结束后进行释放。

🐇new和delete

  • 动态申请内存操作符new
    • new 数据类型T(初始化参数列表)int * point = new int();
    • 功能:在程序执行期间,申请用于存放T类型变量/对象的内存空间,并依初值列表赋以初值。
    • 结果值:
      • 成功:T类型的指针,指向新分配的内存;
      • 失败:抛出异常。
  • 释放内存操作符delete
    • delete 指针p
    • 功能:释放指针p所指向的内存。p必须是new操作的返回值。
    • 注意:New分配的内存必须用delete加以释放。

🐇动态创建多维数组

  • new 类型名T[第1维长度][第2维长度]…;
  • 如果内存申请成功,new运算返回一个指向新分配内存首地址的指针,是一个T类型的数组,数组元素的个数为除最左边一维外各维下标表达式的乘积。
    在这里插入图片描述

📚用vector创建数组对象

  • 使用vector创建数组对象
  • 为什么需要vector?
    • 将动态数组封装,自动创建和删除数组下标越界检查
  • vector动态数组对象的定义
    • vector<元素类型> 数组对象名(数组长度);
    • 例:vector<int> arr(5),​建立大小为5的int数组
  • 对数组元素的引用
    • 与普通数组具有相同形式:数组对象名 [ 下标表达式 ]
    • 但vector数组对象名不表示数组首地址
  • 获得数组长度
    • 用size函数
    • 数组对象名.size()

📚深拷贝与浅拷贝

  • 浅拷贝:实现对象间数据元素的一一对应复制。
  • 深拷贝:当被复制的对象数据成员是指针类型时,不是复制该指针成员本身,而是将指针所指对象进行复制。

📚字符串

  • C++中的String的常用函数用法总结
    在这里插入图片描述

这篇关于高程 | 数组、指针与字符串(c++)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/712039

相关文章

JAVA中整型数组、字符串数组、整型数和字符串 的创建与转换的方法

《JAVA中整型数组、字符串数组、整型数和字符串的创建与转换的方法》本文介绍了Java中字符串、字符数组和整型数组的创建方法,以及它们之间的转换方法,还详细讲解了字符串中的一些常用方法,如index... 目录一、字符串、字符数组和整型数组的创建1、字符串的创建方法1.1 通过引用字符数组来创建字符串1.2

深入理解C++ 空类大小

《深入理解C++空类大小》本文主要介绍了C++空类大小,规定空类大小为1字节,主要是为了保证对象的唯一性和可区分性,满足数组元素地址连续的要求,下面就来了解一下... 目录1. 保证对象的唯一性和可区分性2. 满足数组元素地址连续的要求3. 与C++的对象模型和内存管理机制相适配查看类对象内存在C++中,规

C#中字符串分割的多种方式

《C#中字符串分割的多种方式》在C#编程语言中,字符串处理是日常开发中不可或缺的一部分,字符串分割是处理文本数据时常用的操作,它允许我们将一个长字符串分解成多个子字符串,本文给大家介绍了C#中字符串分... 目录1. 使用 string.Split2. 使用正则表达式 (Regex.Split)3. 使用

在 VSCode 中配置 C++ 开发环境的详细教程

《在VSCode中配置C++开发环境的详细教程》本文详细介绍了如何在VisualStudioCode(VSCode)中配置C++开发环境,包括安装必要的工具、配置编译器、设置调试环境等步骤,通... 目录如何在 VSCode 中配置 C++ 开发环境:详细教程1. 什么是 VSCode?2. 安装 VSCo

vue如何监听对象或者数组某个属性的变化详解

《vue如何监听对象或者数组某个属性的变化详解》这篇文章主要给大家介绍了关于vue如何监听对象或者数组某个属性的变化,在Vue.js中可以通过watch监听属性变化并动态修改其他属性的值,watch通... 目录前言用watch监听深度监听使用计算属性watch和计算属性的区别在vue 3中使用watchE

Java中JSON字符串反序列化(动态泛型)

《Java中JSON字符串反序列化(动态泛型)》文章讨论了在定时任务中使用反射调用目标对象时处理动态参数的问题,通过将方法参数存储为JSON字符串并进行反序列化,可以实现动态调用,然而,这种方式容易导... 需求:定时任务扫描,反射调用目标对象,但是,方法的传参不是固定的。方案一:将方法参数存成jsON字

C++11的函数包装器std::function使用示例

《C++11的函数包装器std::function使用示例》C++11引入的std::function是最常用的函数包装器,它可以存储任何可调用对象并提供统一的调用接口,以下是关于函数包装器的详细讲解... 目录一、std::function 的基本用法1. 基本语法二、如何使用 std::function

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数