C++中指针使用详解(2)指针与函数参数、数值和内存申请释放

一、指针与函数参数:传值、传地址、传引用的区别

1. 普通传值

void foo(int x) {
    x = 10;
}
  • 拷贝变量副本,不影响原值

2. 传指针(地址)

void foo(int* px) {
    *px = 10;
}

int a = 5;
foo(&a); // 传地址
  • 可以修改原变量的值

3. 传引用(C++ 语法糖)

void foo(int& x) {
    x = 10;
}
  • 效果和传指针一样,语法更简洁
  • 本质上编译器仍然使用地址传递

二、堆与栈的内存分配(Stack vs Heap)

特性栈内存(stack)堆内存(heap)
分配方式编译器自动分配程序员手动申请 (new, malloc)
生命周期函数结束自动释放手动释放 (delete, free)
速度相对较慢
空间大小

示例:栈 vs 堆

void stack_example() {
    int a = 5;         // 分配在栈上
    int b[1000];       // 数组也在栈上,超大会爆栈
}

void heap_example() {
    int* pa = new int(5);    // 在堆上
    int* arr = new int[1000]; // 大数组建议放堆上
    delete pa;
    delete[] arr;
}

三、数组与指针的底层实现原理

1. 数组名是常量指针

int arr[5] = {1,2,3,4,5};
int* p = arr; // 等价于 &arr[0]

cout << arr[2] << " == " << *(arr + 2) << endl;

2. 指针模拟数组

int* p = new int[5];
for (int i = 0; i < 5; ++i)
    p[i] = i * 10;

底层数组的访问是通过偏移地址寻址

*(p + i) ↔ p[i]

3. 指针和二维数组

int arr[2][3];         // 实际是一维连续内存
int* p = &arr[0][0];   // 可以线性访问

四、内存申请与释放(new/delete 和 malloc/free)

1. C 风格:malloc / free

int* p = (int*)malloc(sizeof(int) * 10);
p[0] = 1;
free(p);

malloc 不会调用构造函数,适用于 C 或 POD 类型。


2. C++ 风格:new / delete

int* p = new int(5);
int* arr = new int[10];

delete p;
delete[] arr;

new 自动计算大小,并调用构造函数。


3. 自定义结构体对象

struct Point {
    int x, y;
    Point(int a, int b): x(a), y(b) {}
};

Point* pt = new Point(3, 4);
delete pt;

五、常见错误和防坑技巧

错误类型描述
内存泄漏new 后没有 delete,会占用系统内存不释放
野指针使用未初始化或已释放的指针
重复释放两次 delete 同一指针(可用 nullptr 判定)
越界访问指针运算出错,访问了非法内存

安全写法建议

int* p = new int(10);
delete p;
p = nullptr; // 防止二次 delete

六、综合例子(封装动态数组类)

#include <iostream>
using namespace std;

class MyArray {
    int* data;
    int size;
public:
    MyArray(int n): size(n) {
        data = new int[n];
    }

    ~MyArray() {
        delete[] data;
    }

    int& operator[](int index) {
        return data[index];
    }
};

int main() {
    MyArray arr(5);
    for (int i = 0; i < 5; ++i)
        arr[i] = i * 10;

    for (int i = 0; i < 5; ++i)
        cout << arr[i] << " ";
    cout << endl;
}

七、总结结构图

栈(Stack):
 ┌─────────────┐
 │ int a = 5;  │ ← 自动分配、函数返回即释放
 └─────────────┘

堆(Heap):
 ┌─────────────┐
 │ new int(5); │ ← 手动管理,delete 释放
 └─────────────┘

数组与指针:
 arr[i] ↔ *(arr + i)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

点云SLAM

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

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

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

打赏作者

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

抵扣说明:

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

余额充值