C++之指针

参考链接

C++ 指针入门教程

指针是一种特殊的变量,用于存储另一个变量的内存地址。通过使用指针可以直接访问和操作内存,从而实现更灵活和高效的编程。

初识指针

1. 什么是指针?

在计算机中,每个变量都被分配一个唯一的内存地址,用于标识该变量在内存中的位置。

在C++中,指针是一个变量,其值是另一个变量的内存地址。指针的主要作用是通过地址访问变量的值。指针可以用于动态内存分配、数组和字符串操作、函数参数传递等。

下面是一个简单的示例:

int x = 10;
int* ptr = &x;

在这个例子中,x 是一个普通的整数变量,它的值是 10。ptr 是一个指针变量,它存储的是 x 变量的内存地址。我们使用&操作符来获取 x 的地址,并将其赋值给 ptr

2. 指针的声明和初始化

在 C++ 中,我们可以使用以下语法来声明一个指针变量:

data_type* pointer_name;

其中,data_type 是指针指向的变量的数据类型。

下面是一些示例:

int* intPtr;      // 整型指针
double* doublePtr; // 双精度浮点型指针
char* charPtr;     // 字符型指针

我们还可以在声明时初始化指针:

int x = 10;
int* ptr = &x; // 将 x 的地址赋值给 ptr

在这个例子中,我们创建了一个整型变量 x,并将它的地址赋值给指针变量 ptr

指针的使用

1. 使用指针访问数据

使用指针,我们可以间接访问和操作存储在内存中的数据。下面是一些常见的指针操作:

解引用操作符

解引用操作符 * 用于获取指针指向的变量的值。例如:

int x = 10;
int* ptr = &x;
std::cout << "*ptr = " << *ptr << std::endl; // 输出 10

在这个例子中,我们使用 *ptr 来访问 x 的值,而不是直接使用 x

指针运算

我们可以对指针执行一些基本的算术运算,比如加法和减法。这样可以让我们移动指针,指向内存中的其他位置。

int arr[] = {12345};
int* ptr = arr; // ptr 指向数组的第一个元素
std::cout << "*ptr = " << *ptr << std::endl; // 输出 1

ptr++; // 将 ptr 移动到下一个元素
std::cout << "*ptr = " << *ptr << std::endl; // 输出 2

在这个例子中,我们首先让 ptr 指向数组 arr 的第一个元素。然后,我们使用 ptr++ptr 移动到下一个元素。

2. 指针和动态内存分配

指针最常见的用途之一就是动态内存分配。我们可以使用 newdelete 关键字在运行时分配和释放内存块。

int* ptr = new int; // 分配一个整型内存块
*ptr = 20; // 对分配的内存赋值
std::cout << "*ptr = " << *ptr << std::endl; // 输出 20

delete ptr; // 释放内存

在这个例子中,我们使用 new 关键字动态分配了一块整型内存,并通过解引用操作符 * 来访问和修改其值。最后,我们使用 delete 关键字释放了分配的内存。

动态内存分配在处理大型数据结构和复杂算法时非常有用。但需要谨慎使用,以避免内存泄漏等问题。

3. 指针和数组

指针和数组在 C++ 中有着密切的关系。

数组名本身就是一个指向数组首元素的指针。

int arr[] = {12345};
int* ptr = arr; // ptr 指向数组的第一个元素

std::cout << "Element at index 0: " << *ptr << std::endl; // 输出 1
std::cout << "Element at index 1: " << *(ptr + 1) << std::endl; // 输出 2

在这个例子中,我们首先声明了一个整型数组 arr

然后,我们让指针 ptr 指向数组的第一个元素。

接下来,我们使用解引用操作符 * 和指针运算来访问数组中的元素。

需要注意的是,在 C++ 中,数组名和指针是可以互换使用的。也就是说,您可以使用数组名来代替指针,并获得相同的结果。

4. 指针与字符串

C++中的字符串可以表示为字符数组,因此指针也可以用于操作字符串。

int main() {
    char str[] = "Hello, World!";
    char* ptr = str;

    while (*ptr != '\0') {
        std::cout << *ptr;
        ++ptr;
    }

    std::cout << std::endl;

    return 0;
}

在这个示例中,指针ptr用于遍历并输出字符串str中的每个字符,直到遇到字符串结束符'\0'

5. 动态数组

int main() {
    int size;
    std::cout << "请输入数组元素的数量: ";
    std::cin >> size;

    int* arr = new int[size]; // 动态分配数组

    for (int i = 0; i < size; ++i) {
        arr[i] = i + 1;
    }

    std::cout << "数组元素: ";
    for (int i = 0; i < size; ++i) {
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;

    delete[] arr; // 释放动态分配的数组

    return 0;
}

在这个示例中,我们动态分配了一个整数数组,并在程序结束时释放了分配的内存。

6. 指向指针的指针

指针不仅可以指向普通变量,还可以指向其他指针。这种指针称为“指向指针的指针”或“二级指针”。

int main() {
    int var = 3000;
    int* ptr = &var;
    int** ptr2 = &ptr;

    std::cout << "var: " << var << std::endl;
    std::cout << "*ptr: " << *ptr << std::endl;
    std::cout << "**ptr2: " << **ptr2 << std::endl;

    return 0;
}

在这个示例中,ptr2是一个指向指针ptr的指针,通过**ptr2可以访问到变量var的值。

7. 函数指针

函数指针是指向函数的指针,可以用于调用函数和实现回调机制。

#include <iostream>

void greet() {
    std::cout << "Hello, World!" << std::endl;
}

int main() {
    void (*funcPtr)() = greet; // 声明一个函数指针并初始化
    funcPtr(); // 通过指针调用函数

    return 0;
}

在这个示例中,funcPtr是一个指向函数greet的指针,通过funcPtr()可以调用该函数。

8. const修饰指针

const关键字可以用于修饰指针,提供不同的含义:

  1. 指向常量的指针:指针指向的值不能被修改。
  2. 常量指针:指针本身不能被修改。
  3. 指向常量的常量指针:指针本身和指针指向的值都不能被修改。

指向常量的指针

int main() {
    int value = 42;
    const int* ptr = &value;

    // *ptr = 50; // 错误:不能修改指向的值
    value = 50; // 可以修改原始变量

    std::cout << "Value: " << *ptr << std::endl;//50

    return 0;
}

常量指针

int main() {
    int value1 = 42;
    int value2 = 100;
    int* const ptr = &value1;

    *ptr = 50; // 可以修改指向的值
    // ptr = &value2; // 错误:不能修改指针本身

    std::cout << "Value: " << *ptr << std::endl;//50

    return 0;
}

指向常量的常量指针

int main() {
    int value = 42;
    const int* const ptr = &value;

    // *ptr = 50; // 错误:不能修改指向的值
    // ptr = &value; // 错误:不能修改指针本身

    std::cout << "Value: " << *ptr << std::endl;

    return 0;
}

常见指针问题和注意事项

使用指针时需要注意一些常见的问题:

  1. 野指针: 未初始化或已经释放的指针,访问它们可能会导致程序崩溃。
  2. 内存泄漏: 动态分配的内存没有被适当释放,会导致内存消耗越来越大。
  3. 数组越界: 使用指针访问数组时,需要小心不要越界。
  4. 空指针: 试图访问空指针(值为 NULLnullptr)会导致程序崩溃。

为了避免这些问题,在使用指针时请务必小心谨慎,并遵循以下最佳实践:

  • 始终初始化指针,避免使用野指针。
  • 及时释放动态分配的内存,防止内存泄漏。
  • 确保指针始终指向有效的内存地址,不要越界访问。
  • 在使用指针前检查其是否为空,避免访问空指针。
  • 9
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

abcccccccccccccccode

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值