C++ 指针

C++ 中的指针是一个存储内存地址的变量。指针可以指向任何数据类型,包括基本类型、对象、甚至函数。以下是关于指针的核心知识点:

1. 指针的声明和初始化

指针声明时使用 * 表示它是一个指针类型。指针变量保存的是另一个变量的内存地址。

在这段代码中:

  • a 是一个整型变量,值为 10
  • p 是一个指向整型变量的指针,它保存的是变量 a 的地址。

&a 是取变量 a 的地址。p 保存了这个地址,并通过 *p 可以访问 a 的值。

2. 解引用(Dereferencing)

使用解引用操作符 * 可以访问指针所指向的变量的值:

这里的 *p 访问的是 p 指向的 a 的值,即 10

3. 空指针(Null Pointer)

指针可以指向 nullptr,表示它不指向任何有效的内存位置。未初始化的指针可能指向随机的内存地址,使用这些指针会导致未定义行为。因此,通常将未初始化的指针设置为 nullptr

int* ptr = nullptr;
 

4. 指针的运算

指针可以进行算术运算,特别是在数组的上下文中。对指针进行加减操作时,会根据指针指向的数据类型进行调整。

int arr[] = {1, 2, 3, 4};
int* p = arr;  // 指向数组的首地址
p++;  // 地址偏移, p 指向下一个元素,即 arr[1]

5. 指针和数组

数组的名称其实就是指向第一个元素的指针。因此,你可以通过指针来访问数组元素。

int arr[] = {1, 2, 3};
int* p = arr;
cout << *p;    // 输出 1
cout << *(p+1);  // 输出 2
 

6. 指针与函数

指针可以作为函数的参数,将参数通过指针传递允许函数修改调用者的变量。

void modify(int* p) {
    *p = 20;
}

int main() {
    int x = 10;
    modify(&x);  // 传递 x 的地址
    cout << x;  // 输出 20
    return 0;
}
 

7. 常量指针和指向常量的指针

C++ 提供了两种指针常量:

  • 指向常量的指针 (const T* p):指针可以指向不同的地址,但不能修改指向的值。
  • 常量指针 (T* const p):指针本身是常量,不能改变它指向的地址,但可以修改地址中的值。const int* p1;  // p1 不能修改指向的值,但可以指向其他地址
    int* const p2 = &a;  // p2 不能指向其他地址,但可以修改值。

    8. 指针的注意事项

  • 野指针:未初始化或已经释放的指针指向非法内存区域,使用它会导致未定义行为。使用前应确保指针有效,必要时将其设置为 nullptr
  • 内存泄漏:如果使用 new 动态分配内存,一定要使用 delete 释放内存,否则会导致内存泄漏。

        int* p = new int(10);  // 动态分配
        delete p;  // 释放内存
        p = nullptr;  // 防止悬空指针

9. 指向指针的指针(Pointer to Pointer)

指针也可以指向另一个指针,称为 "指向指针的指针"。使用时需要多个 * 来访问不同层次的指针。

int a = 10;
int* p = &a;     // p 指向 a
int** pp = &p;   // pp 指向 p 的地址
cout << **pp;    // 输出 10
在这段代码中,pp 是一个二级指针,它保存了一级指针 p 的地址。通过 **pp 可以访问到 a 的值。

10. 动态内存分配

在 C++ 中,使用 newdelete 来进行动态内存分配。指针在动态内存分配中扮演了重要角色。

单个变量的动态分配

int* p = new int;  // 分配一个整型空间
*p = 10;
delete p;          // 释放内存
 

数组的动态分配

int* arr = new int[5];  // 分配整型数组
arr[0] = 1;
arr[1] = 2;
delete[] arr;  // 使用 delete[] 释放数组
 

11. 函数指针

指针不仅可以指向变量,还可以指向函数。函数指针用于保存函数的地址,并可以通过它调用函数。函数指针常用于回调函数和事件处理。

int add(int a, int b) {
    return a + b;
}

int (*funcPtr)(int, int) = add;  // 定义指向函数的指针
cout << funcPtr(2, 3);  // 通过函数指针调用 add,输出 5

12. 指针和类

指针也可以指向类的对象。通过指针,可以访问对象的成员函数和成员变量。

class MyClass {
public:
    int data;
    void show() { cout << data; }
};

int main() {
    MyClass obj;
    obj.data = 10;

    MyClass* ptr = &obj;  // 指针指向对象
    ptr->show();          // 通过指针访问成员函数,输出 10
    return 0;
}
 

13. this 指针

每个类的成员函数都有一个隐藏的指针,名为 this,它指向调用该函数的对象本身。

class MyClass {
public:
    int data;
    void setData(int data) {
        this->data = data;  // 使用 this 指针访问当前对象的成员变量
    }
};

14. 常量指针和指针常量的结合

你可以组合指向常量的指针和常量指针,创建复杂的指针类型:

  • const int* const ptr:指针既不能修改指向的内容,也不能修改它指向的地址。

15. 智能指针(Smart Pointers)

C++11 引入了智能指针,用来管理动态内存分配,避免手动 delete。标准库提供了三种主要的智能指针:

std::unique_ptr:独占所有权的智能指针,不能共享指向的对象。

std::unique_ptr<int> ptr = std::make_unique<int>(10);


std::shared_ptr:可以共享所有权的智能指针,多个指针可以指向同一对象。对象在最后一个 shared_ptr 被销毁时自动释放内存。

std::shared_ptr<int> p1 = std::make_shared<int>(20);
std::shared_ptr<int> p2 = p1;  // p1 和 p2 共享所有权

std::weak_ptr:一种不增加引用计数的智能指针,常与 std::shared_ptr 结合使用,避免循环引用。

std::weak_ptr<int> wp = p1;  // wp 不增加 p1 的引用计数

16. 指针与 void*

void* 是一种通用指针类型,能指向任何类型的数据。但使用 void* 进行解引用时,必须先将其强制转换为具体类型的指针。

int a = 10;
void* ptr = &a;
cout << *(int*)ptr;  // 需要将 void* 转换为 int*
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值