C++中的指针、引用和数组

参考文档:《21天学通C++(第8版)》

C++中对于指针、引用和数组使用时,充斥着 * 、& 、[]符号,对于像我这样的初学者面对这些符号难免会陷入混乱。

当然,C++中对符号 * 、& 、[] 赋予了多重意义也是让人容易混乱的原因。

这篇文章是在《21天学通C++》第8章内容基础上,进行总结和提炼,以方便自己和网友们回顾使用。没有基础的同学,可以参考书籍中第8章内容进行学习。

版本号:C++14

先说说三者的概念:

指针:指针是一个变量,用于存储内存地址。

引用:引用是一个别名,它提供了对变量的另一个名称。一旦引用初始化为一个对象,就不能再改变为指向另一个对象。

数组:数组是一种数据结构,用于存储多个相同类型的元素。

来一个表格总结下三个符号的用法,可以先过目一下,不理解没关系,看完下文回头再看会更清晰:

符号

声明

运算符

*

声明指针

解除引用运算符(获取地址所存储的值)

&

声明引用

引用运算符(获取变量地址)

[]

声明数组

数组下标运算符

一.变量声明

三者在C++中是如何声明的呢:

1.声明指针(*)

PointedType * PointerVariableName;

int *pointsToInt = NULL;

在C++中,声明指针有三种方式,且都是合法的,可以根据自己的喜好选择其中一种:

int* p
int *p
int * p

2.声明引用(&)

VarType original = Value; 
VarType& ReferenceVariable = original;

int original = 30;
int& ref1 = original;

同样引用的声明也有三种方式:

int& ref
int &ref
int & ref

3.声明数组([])

// elements为数组长度
type name[elements];

int myNumbers [5];

分别用三种符号对三者进行了声明。让我们造成困惑的是,这三种符号,在表达式中还可以作为运算符来使用。

二.表达式中的运算符

在表达式中,这些运算符的使用场景:

1.引用运算符(&)

&作为运算符还有个场景是 "按位AND" 运算,这里不做介绍

获取变量地址,用指针来存储地址。(引用运算符也叫地址运算符)

// 定义一个变量
int a = 10;
// 定义一个指向int类型的指针,并初始化地址
int* pointer = &a;

2.解除引用运算符(*)

*还有个作用是乘法运算符,这里不做介绍

解引用运算符用于访问指针所指向的内存地址中存储的值。(解除引用运算符也叫间接运算符)

int age = 30; 

int* pointsToInt = &age;
// 打印指针地址指向的内存中的值(*pointsToInt)
cout << "*pointsToInt = " << dec << *pointsToInt << endl;

将解除引用运算符(*)用于指针时,如果指针未初始化,它所在的内存单元将包含随机值,此时对其解除引用可能会导致程序崩溃或产生意外结果。

3.数组下标运算符([])

用于访问数组中的元素。下标运算符使用方括号 [],并且可以用于一维数组和多维数组。

int arr[5] = {1, 2, 3, 4, 5};
int x = arr[2];  // 获取数组arr中索引为2的元素,即第3个元素

三.其他注意事项

1.动态分配内存和释放

使用new关键字来动态申请内存,如果成功,将返回一个指针,指向分配的内存

delete对动态申请的内存进行释放

Type* Pointer = new Type; // request memory for one element
Type* Pointer = new Type[numElements]; // request memory for numElements

delete Pointer; // release memory allocated above
delete[] Pointer; // release block allocated above

2.const用于指针

关键字const在指针前修饰,可以对指针指向的地址地址指向的数据能否修改进行限制。

限制

例子

允许✔️

不允许❌

常量指针

指针本身为常量,指向地址不能修改,但可修改指针指向的数据

int daysInMonth = 30;

int* const pDaysInMonth = &daysInMonth;

*pDaysInMonth = 31;

(int daysInLunarMonth = 28; )

pDaysInMonth = &daysInLunarMonth;

指向常量的指针

指针指向的数据为常量不能修改,但可以修改指针包含的地址,即指针可以指向其他地方

int hoursInDay = 24;

const int* pointsToInt = &hoursInDay;

int monthsInYear = 12;

pointsToInt = &monthsInYear;

*pointsToInt = 13;

int* newPointer = pointsToInt;(不允许负值给非const变量)

指向常量的常量指针

指针包含的地址以及它指向的值都不能修改(这种组合最严格)

int hoursInDay = 24;

const int* const pHoursInDay = &hoursInDay;

*pHoursInDay = 25;

int daysInMonth = 30;

pHoursInDay = &daysInMonth;

将指针传递给函数时,这些形式的 const 很有用。函数参数应声明为最严格的 const 指针,以确保函数不会修改指针指向的值。这可禁止程序员修改指针及其指向的数据。

3.数组和指针

数组名是一个指针,指向第一个元素。由于数组变量就是指针,因此也可将用于指针的解除引用运算符(*)用于数组。同样,可将数组下标运算符([])用于指针。

int main() 
{ 
    const int ARRAY_LEN = 5; 

    // 有5个元素的静态数组
    int myNumbers[ARRAY_LEN] = {24, -1, 365, -999, 2011}; 

    // 指向数组第一个元素的指针
    int* pointToNums = myNumbers; 

    // 打印数组中的元素
    cout << "使用*运算符打印数组" << endl; 
    for (int index = 0; index < ARRAY_LEN; ++index) 
        cout << "Element " << index << " = " << *(myNumbers + index) << endl; 

    cout << "使用[]运算符打印数组" << endl; 
    for (int index = 0; index < ARRAY_LEN; ++index) 
        cout << "Element " << index << " = " << pointToNums[index] << endl; 

    return 0; 
}

数组的限制:

数组类似于在固定内存范围内发挥作用的指针。可将数组赋给指针,但不能将指针赋给数组,因为数组是静态的,不能用作左值。

4.引用

引用是变量的别名。声明引用时,需要将其初始化为一个变量,因此引用只是另一种访问相应变量存储的数据的方式。

引用可以使用在函数的参数中,当参数占用内存过大时,形参的复制步骤会有很大开销,引用的使用可以避免这种开销浪费。

ReturnType DoSomething(Type& parameter);

下面解释一下引用传递为何可以避免开销浪费:

C++中有两种参数传递方式:值传递引用传递

在值传递中,C++会在内存中创建该值的一个拷贝,并将这个拷贝传递给函数。这意味着函数内部对参数的修改不会影响到原始值。如下是值传递的例子:

#include <iostream>
using namespace std;

void modifyValue(int x) {
    x = 10;
}

int main() {
    int num = 5;
    modifyValue(num);
    cout << num;  // 输出为5,因为函数内部对参数的修改不会影响原始值
    return 0;
}

使用引用传递,可以避免创建拷贝,还可以直接操作原始值。如下是引用传递参数的例子:

#include <iostream>
using namespace std;

void modifyValue(int &x) {
    x = 10;
}

int main() {
    int num = 5;
    modifyValue(num);
    cout << num;  // 输出为10,因为函数内部直接修改了原始值
    return 0;
}

将const 用于引用,可以限制通过引用修改它指向的变量的值:

int original = 30; 
const int& constRef = original; 
constRef = 40; // 无法通过编译
  • 23
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值