C++指针详解

本文深入探讨了C++中的指针,包括声明和初始化指针,指针与内存管理的关系,如new和delete的使用,以及指针在结构体、数组、字符串和const中的应用。同时,介绍了函数指针的概念,展示了如何使用函数指针传递函数地址。文章强调了正确使用指针以避免内存泄漏的重要性,并提供了实例代码进行说明。
摘要由CSDN通过智能技术生成

声明和初始化指针

int a = 5;
int* pi = &a
cout<<*pi<<endl;

可以理解为pi的类型是指向int的指针(int*)。也就是说,pi是指针( 地址),而*piint,而不是指针

int* pi;
*pi = 23333;

一定 要在 对 指针 应用 解除 引用 运算符(*) 之前, 将 指针 初始 化为 一个 确定 的、 适当 的 地址。 这是 关于 使用 指针 的 金科玉律。 如果指针未被初始化,不知道他的地址是啥的情况下,不能随意的给他指向的内存块赋值,如果 pi 的 值 碰巧 为 1200, 计算机 将把 数据 放在 地址 1200 上, 即使 这 恰巧 是 程序 代码 的 地址。 pi指向 的 地方 很可能 并不是 所要 存储 23333 的 地方。 这种 错误 可能 会 导致 一些 最 隐匿、 最难 以 跟踪 的 bug。

使用new来在运行时分配内存

int* pi = new int;
delete pi;

new int 告诉 程序, 需要 适合 存储 int 的 内存。 new 运算符 根据 类型 来 确定 需要 多少 字节 的 内存。 然后, 它 找到 这样 的 内存, 并 返回 其 地址。 接下来, 将 地址 赋 给 pi, pi 是 被 声明 为 指向 int 的 指针。 现在, pi 是 地址, 而* pi 是 存储 在那里 的 值。当 需要 内存 时, 可以 使用 new 来 请求, 这 只是 C++ 内存 管理 数据 包 中有 魅力 的 一个方面。 另一个 方面 是 delete 运算符, 它 使得 在使 用完 内存 后, 能够 将其 归还 给 内存 池, 这是 通向 最 有效地 使用 内存 的 关键 一步。

char* getName() {
    int* mm = new int;
    *mm = 5;
    char temp[5] = "1234";
    char* pn = new char[strlen(temp) + 1];
    strcpy(pn, temp);
    return pn;
}
int mian(){
	char* pn = getName();
    cout << pn << endl;
    delete[] pn;
}

上述代码中getName()执行结束后,temp使用的内存将会自动释放,pn使用的内存在main函数释放,而mm指向的内存将不会被释放。如果使用new申请的内存mm没有得到释放,那么相应的内存将不会被再次利用。如果此时没有指向mm的指针,mm将无法被释放,那么会将会造成内存泄漏。

使用指针

指针与结构体

struct st {
    int a;
    string b;
    st(int a, string b) {
        this->a = a;
        this->b = b;
    }
};

void pointAndStruct()
{
    st* st3 = new st(577, "dd");
    //A->B A是指针,获取A中的成员B 相当于 (*A).B;
    cout << st3->a << endl;
    //三种赋值方式
    (*st3).a = 588;
    st3->a = 599;
    *&st3->a = 611;
    cout << (*st3).a << endl;//611
    //释放内存(释放内存的意思当前内存可以再次new了,所以只能用delete 释放使用new分配的内存)
    delete st3;
}

指针与数组

void pointAndArray() 
{
    //手指
    int* p = new int[2]{ 0,1 };
    cout << p[0] << endl;       //0
    cout << *p << endl;         //0
    cout << *(p + 1) << endl;   //1
    int* p1 = p + 1;
    cout << p << endl;          //006E5858
    cout << p1 << endl;         //006E585C
    //加 1 的 结果 等于 原来 的 地址 值 加上 指向 的 对象 占 用的 总 字节数。
    delete[]p;
}

指针与字符串

void pointAndString() 
{
    //末尾的被'\0',自动填充,这是必不可少的
    char s5[7] = "123456";              //实际上 = {'1','2','3','4','5','6','\0'}
    cout << (int*)s5 << endl;           //获取地址
    auto s6 = s5 + 1;
    cout << s6 << endl;                 //23456(输出会到'\0')停止
    const char* s7 = "12345";           //字符串 字 面值 是 常量, 这就 是 为什么 代码 在 声明 中 使用 关键字 const 的 原因。
    char* s8 = new char[5]{ '1','2' };  //末尾自动补'\0',但不能new char[2]{ '1','2' }这样
    int as = 5;
    cout << s8 << endl;
    cout << strlen(s8) << endl;         //2
    delete[]s8;
}

指针与const

typedef int* int_point;
int main()
{
    int a[5] = { 1,2,3,4,5 };
    int_point ap = a;
    cout << ap[0] << endl;  //1
    const int* ac;          //*ac 是const 不能被修改
    ac = ap;
    ac++;
    cout << *ac << endl;    //2
    int* const af = a;      //af 是const 不能被修改
    *af = 6;
    cout << *a << endl;     //6
}

函数指针

函数指针能够使函数地址作为参数传递

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

void printAdd(int a,int b,int (*pf)(int, int)) {
	cout << (*pf)(a, b) << endl;
	//cout << pf(a, b) << endl;//两种方式都可以,第一种更规范,第二种更方便
}
int main()
{
	printAdd(4, 5, add);//add代表函数add(int a,int b)的地址
}

更复杂的函数指针

typedef const double* (*p_func)(const double*, int);//减少代码犯错率(有点委托的味道了)
const double* f1(const double* ar, int b) {
	return ar;
}
const double* f2(const double ar[], int b) {
	return ar + 1;
}
int main()
{
	double ar[3] = { 1,2,3 };
	p_func p1 = f1;
	p_func p2 = f2;
	cout << *p1(ar, 5) << endl;//1
	cout << *p2(ar, 5) << endl;//2
	p_func pa[2] = { f1,f2 };
	cout << *pa[0](ar, 5) << endl;//1
	p_func(*pd)[2] = &pa;//一个指向有两个p_func元素数组的指针=>(*pd)[0] = pa[0],(*pd)[1] = pa[1]
	cout << *(*pd)[1](ar, 5) << " " << (*pd)[1](ar, 5) << endl;//2 001CFC34
}

摘要

Stephen Prata. C++ Primer Plus(第6版)中文版(异步图书) (C和C++实务精选) (p. 295 - p380). 人民邮电出版社. Kindle 版本.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值