用户工具

站点工具


cplus:第八章指针与引用

第八章 指针与引用

指针和引用是C++中两个极其重要的概念,它们是实现动态内存管理、高效数据传递和复杂数据结构的基础。本章将深入探讨指针与引用的原理、用法以及它们之间的关系。

8.1 指针基础

8.1.1 什么是指针

指针是一个变量,其值为另一个变量的内存地址。通过指针,我们可以直接访问和操作内存中的数据。

内存地址的概念

在计算机中,每个变量都存储在内存的某个位置,这个位置有一个唯一的地址。就像每家每户都有一个门牌号一样,内存中的每个字节都有一个地址。

#include <iostream>
using namespace std;
 
int main() {
    int num = 100;
    cout << "变量num的值: " << num << endl;
    cout << "变量num的地址: " << &num << endl;
    return 0;
}

声明指针变量

指针变量的声明格式为:

数据类型 *指针变量名;

例如:

int *pInt;      // 指向int类型的指针
double *pDouble; // 指向double类型的指针
char *pChar;     // 指向char类型的指针
void *pVoid;     // 通用指针,可以指向任何类型

8.1.2 指针的初始化与使用

获取变量的地址

使用取地址运算符 & 可以获取变量的内存地址:

int num = 100;
int *p = &num;  // p存储了num的地址

解引用运算符

使用解引用运算符 * 可以访问指针所指向的值:

#include <iostream>
using namespace std;
 
int main() {
    int num = 100;
    int *p = &num;
 
    cout << "num的值: " << num << endl;
    cout << "p的值(地址): " << p << endl;
    cout << "*p的值: " << *p << endl;  // 通过指针访问num的值
 
    *p = 200;  // 通过指针修改num的值
    cout << "修改后num的值: " << num << endl;
 
    return 0;
}

空指针与野指针

int *p1 = nullptr;  // C++11推荐的方式,空指针
int *p2 = NULL;     // C风格,等价于0
int *p3 = 0;        // 直接赋值为0
 
// int *p4;         // 错误!野指针,未初始化

8.2 指针与数组

8.2.1 数组名的本质

在C++中,数组名本质上是一个指向数组首元素的常量指针。

#include <iostream>
using namespace std;
 
int main() {
    int arr[5] = {10, 20, 30, 40, 50};
 
    cout << "arr的值(首地址): " << arr << endl;
    cout << "&arr[0]: " << &arr[0] << endl;
    cout << "*arr: " << *arr << endl;  // 10
 
    // 通过指针访问数组元素
    int *p = arr;
    for (int i = 0; i < 5; i++) {
        cout << "*(p+" << i << ") = " << *(p + i) << endl;
        // 等价于 p[i] 或 arr[i]
    }
 
    return 0;
}

8.2.2 指针运算

指针支持以下运算: - p + n:指针向后移动n个元素的位置 - p - n:指针向前移动n个元素的位置 - p++ / p–:指针向后/向前移动一个元素 - p - q:两个指针之间的距离(元素个数)

#include <iostream>
using namespace std;
 
int main() {
    int arr[] = {10, 20, 30, 40, 50};
    int *p = arr;
 
    cout << "初始位置: *p = " << *p << endl;  // 10
 
    p++;  // 移动到下一个元素
    cout << "p++后: *p = " << *p << endl;     // 20
 
    p += 2;  // 向前移动2个元素
    cout << "p+=2后: *p = " << *p << endl;    // 40
 
    int *q = arr;
    cout << "p - q = " << p - q << endl;      // 3,相隔3个元素
 
    return 0;
}

8.2.3 指针与多维数组

#include <iostream>
using namespace std;
 
int main() {
    int matrix[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };
 
    // 使用指针访问二维数组
    int (*p)[4] = matrix;  // p指向包含4个int的数组
 
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 4; j++) {
            cout << *(*(p + i) + j) << " ";  // 等价于 matrix[i][j]
        }
        cout << endl;
    }
 
    return 0;
}

8.3 指针与字符串

8.3.1 C风格字符串

#include <iostream>
#include <cstring>
using namespace std;
 
int main() {
    // 字符串常量
    const char *str1 = "Hello, World!";
 
    // 字符数组
    char str2[] = "Hello";
 
    cout << "str1: " << str1 << endl;
    cout << "str2: " << str2 << endl;
    cout << "strlen(str1): " << strlen(str1) << endl;
 
    // 遍历字符串
    const char *p = str1;
    while (*p != '\0') {
        cout << *p;
        p++;
    }
    cout << endl;
 
    return 0;
}

8.3.2 字符串指针数组

#include <iostream>
using namespace std;
 
int main() {
    const char *days[] = {
        "Monday",
        "Tuesday",
        "Wednesday",
        "Thursday",
        "Friday",
        "Saturday",
        "Sunday"
    };
 
    for (int i = 0; i < 7; i++) {
        cout << days[i] << endl;
    }
 
    return 0;
}

8.4 指针与函数

8.4.1 指针作为函数参数

通过指针参数,函数可以修改调用者的变量。

#include <iostream>
using namespace std;
 
// 交换两个数的值(使用指针)
void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}
 
int main() {
    int x = 10, y = 20;
    cout << "交换前: x=" << x << ", y=" << y << endl;
 
    swap(&x, &y);
 
    cout << "交换后: x=" << x << ", y=" << y << endl;
    return 0;
}

8.4.2 数组作为函数参数

#include <iostream>
using namespace std;
 
// 计算数组元素之和
int sum(int *arr, int size) {
    int total = 0;
    for (int i = 0; i < size; i++) {
        total += arr[i];
    }
    return total;
}
 
// 或者使用以下形式
int sum2(int arr[], int size) {
    int total = 0;
    for (int i = 0; i < size; i++) {
        total += *(arr + i);
    }
    return total;
}
 
int main() {
    int numbers[] = {1, 2, 3, 4, 5};
    int size = sizeof(numbers) / sizeof(numbers[0]);
 
    cout << "数组元素之和: " << sum(numbers, size) << endl;
 
    return 0;
}

8.4.3 函数指针

函数指针是指向函数的指针,可以用来实现回调函数等高级功能。

#include <iostream>
using namespace std;
 
// 定义函数类型
int add(int a, int b) {
    return a + b;
}
 
int subtract(int a, int b) {
    return a - b;
}
 
int multiply(int a, int b) {
    return a * b;
}
 
int main() {
    // 声明函数指针
    int (*operation)(int, int);
 
    operation = add;
    cout << "10 + 5 = " << operation(10, 5) << endl;
 
    operation = subtract;
    cout << "10 - 5 = " << operation(10, 5) << endl;
 
    operation = multiply;
    cout << "10 * 5 = " << operation(10, 5) << endl;
 
    return 0;
}

8.5 引用

8.5.1 引用的概念

引用是变量的别名,它为已存在的变量提供另一个名字。引用必须在声明时初始化,且不能改变引用的对象。

#include <iostream>
using namespace std;
 
int main() {
    int num = 100;
    int &ref = num;  // ref是num的引用
 
    cout << "num: " << num << endl;
    cout << "ref: " << ref << endl;
 
    ref = 200;  // 通过引用修改值
    cout << "修改后num: " << num << endl;
 
    cout << "&num: " << &num << endl;
    cout << "&ref: " << &ref << endl;  // 地址相同
 
    return 0;
}

8.5.2 引用作为函数参数

引用参数提供了一种更优雅的“按引用传递”方式。

#include <iostream>
using namespace std;
 
// 使用引用交换两个数
void swap(int &a, int &b) {
    int temp = a;
    a = b;
    b = temp;
}
 
int main() {
    int x = 10, y = 20;
    cout << "交换前: x=" << x << ", y=" << y << endl;
 
    swap(x, y);  // 不需要取地址符
 
    cout << "交换后: x=" << x << ", y=" << y << endl;
    return 0;
}

引用 vs 指针参数

特性 指针 引用
——————
语法 需要解引用(*) 直接使用
空值 可以为nullptr 不能为空
重新赋值 可以指向不同对象 始终绑定同一对象
安全性 需要检查空指针 更安全

8.5.3 引用作为返回值

#include <iostream>
using namespace std;
 
int arr[] = {10, 20, 30, 40, 50};
 
// 返回数组元素的引用
int &getElement(int index) {
    return arr[index];
}
 
int main() {
    cout << "修改前: " << arr[2] << endl;
 
    getElement(2) = 100;  // 通过引用返回值修改数组元素
 
    cout << "修改后: " << arr[2] << endl;
 
    return 0;
}

8.5.4 常量引用

常量引用用于防止函数修改传入的参数,同时避免拷贝开销。

#include <iostream>
#include <string>
using namespace std;
 
// 使用const引用传递大型对象
void printString(const string &str) {
    cout << str << endl;
    // str = "new";  // 错误!不能修改const引用
}
 
int main() {
    string text = "Hello, World!";
    printString(text);
    return 0;
}

8.6 指针与引用的比较

特性 指针 引用
——————
定义 存储地址的变量 变量的别名
初始化 可以不初始化 必须立即初始化
空值 可以为空(nullptr) 不能为空
修改绑定 可以指向不同对象 不能改变绑定的对象
内存占用 占用内存存储地址 不占用额外内存
使用语法 需要解引用(*) 直接使用
算术运算 支持 不支持
多级间接
cplus/第八章指针与引用.txt · 最后更改: 127.0.0.1