您现在的位置是:首页 > 数码 > 

指针中的战斗机

2025-07-27 19:51:45
指针中的战斗机 指针是C语言中的精髓,智能指针是C中的王炸! 温故知新,可以为师。在开启智能指针学习篇章前,先来探望老朋友—C语言中的精髓—指针。指针的本质是变量,何为变量,变量就是用特定的数据类型做的mooncake,可大可小,例如有 char、int 、sho

指针中的战斗机

指针是C语言中的精髓,智能指针是C中的王炸!

温故知新,可以为师。在开启智能指针学习篇章前,先来探望老朋友—C语言中的精髓—指针。指针的本质是变量,何为变量,变量就是用特定的数据类型做的mooncake,可大可小,例如有 char、int 、short、double等基础类型,还有就是变量在程序运行时可以被改变。
照本宣科,拿课本里的一句话,“指针变量用于保存变量的地址,通过所保存的地址操作变量。” 这看似简单的一句话,被难倒的初学者不计其数。所以有必要用标新立异的形象比喻来阐明其本质,指针和所指向的变量之间的关系类似于邮差与信箱,邮差知道了信箱的具体位置,就可以往信箱塞信或者拿信。

#include<stdio.h>int main(int argc,char* ar[])
{int a = 1;int b = 0;int* p = &a;	// 取地址操作,指针 p 指向了变量 a*p = 2;		// (寄信)相当于 a = 2;运算过后 a 的值为 2;b = *p  ;	// (取信)等价于 b = a  ; 即 a 加上再赋值给 b// 运算过后 b = 5;return 0;
}

信随意拿,也随意放,有没有觉得这个邮差权力好像有点大啊 !其实,我想说指针的能力真的是太强大了,但是,有无相生,难易相成,任何事物都有两面性,指针也不例外,如果滥用指针随意修改变量值,可能会导致系统崩溃!!!
为了解决一系列的问题,于是乎,C语言就生产了指针常量,常量指针,常量指针常量,初学者大概率搞不明白说的是什么。话不多说,先上代码!

int b = 1;ct int* p1 = &b;int* ct p2 = &b;int ct* p = &b;ct int* ct p4 = &b; 

指针p1、p2、p、p4都指向了同一个变量,坦白说,p1指向的内容不可变,p2指向的地址不可变,p指向的内容不可变,p4指向的内容和地址都不可变。记住一句话就可以了,左数据右地址。
有时候指针很复杂,例如:

int*(*(*p)(int*))(int*);
int (*(*p)(int*))[10];

乍一看还以为是乱码,这样的代码除了吓人之外,没半毛钱用。使用指针的时候,尽量避开形式过于复杂的指针。

另外,指针最大的危害在于内存泄漏,什么是内存泄漏(Memory Leakage),最为恰当的比喻,就是借钱不还。

//C语言程序#include <stdio.h>
#include <malloc.h>int main(int argc,char* ar[])
{int c = 0;int* p = (int* )malloc(sizeof(int));  //借钱了*p = 10;c = *p;printf(%d\n,c);return 0;	// 没还钱(没有free)
}
//C程序#include <iostream>using namespace std;int main(int argc,char* ar[])
{int* p = new int(10);	// 借钱了int c = 0;c = *p;cout << c << endl;return 0;		// 没还钱(没有delete)
}

如此简短的程序,想必读者一定洞若观火,有错是很明显的,解决也是轻而易举,分分钟的事情。但当置身于成千上万行代码的海洋中,无助地感叹,头发又少了!
其实,还钱,90%都是因为忘记了,哈哈对不对?所以花呗自动还款挺好的。高级一点的语言如Java语言,就有内存回收机制,再不担心借钱不还了。虽然C中没有这样优秀的机制,但是,我们可以充分利用现有的资源来实现目标。很明显我们需要人工的智能,C中有两个特殊的无返回值的函数会被编译器自动调用,那就是构造函数和析构函数,如果在构造函数(借钱)向堆空间申请内存,在析构函数中(还钱)释放申请的内存不就完美解决问题了吗?
先回顾一下,构造函数与析构函数的用法。

//C
#include <iostream>
#include <string>using namespace std;class Employee
{
private:string m_name;
public:Employee(ct string& name)	// 构造函数{m_name = name;cout << m_name << endl;}~Employee()			// 析构函数{cout << m_name << endl;}
};int main(int argc,char* ar[])
{Employee ep1(xiaoming);  // 创建了一个对象,构造函数自动被调用return 0;		   // 程序结束时,析构函数被调用 
}

要实现智能指针,还有一个关键要素,那就是操作符重载,简单来说就是把系统中预定义操作符如 - * / = 等进行重载,当然啦,在C中还有另外一个重要的重载概念,函数重载,函数重载有待下回分解。指针操作符就两个,* , -> 。激动人心的时刻来了,待我疾速实现一个智能指针。

#include <iostream>
#include <string>using namespace std;class Test	// 实际要操作的指针对象
{
private:string m_name;
public:Test(ct string s)	// 构造函数里输出调试信息{m_name = s;cout << My name is  << m_name << endl;}Test(ct Test& obj){m_name = _name;}Test& operator = (ct Test& obj) // 赋值符重载,返回对象的引用,目的是不改变赋值符原义{if( this != &obj )	// 判断是否为同一个对象{m_name = _name;}}void print_name(){cout << m_name << endl;}~Test(){	cout << Goodbye  << m_name << endl;}	// 析构函数也输出调式信息
};class Smart_pointer	// 真正的智能指针
{
private:Test* pt;	// 把要使用对象作为私有成员
public:Smart_pointer(Test* p = ULL)// 使用时在堆空间创建一个对象作为参数{pt = p; }Smart_pointer(ct Smart_pointer& obj){this->pt = obj.pt;	// 堆空间使用权力的转移ct_cast<Smart_pointer&>(obj).pt = ULL; // 真正的转移,把之前的置空}Smart_pointer& operator = (ct Smart_pointer& obj){if( this != &obj ){this->pt = obj.pt;ct_cast<Smart_pointer&>(obj).pt = ULL;}}Test* operator -> ()	// 指针操作符重载,返回对象的地址{return pt;}Test& operator * ()	// 指针操作符重载,返回要使用的对象,并且不改变其原义{return *pt;}bool isULL()	// 判断指针是否为空{return ( this == ULL );}~Smart_pointer(){delete pt;	// 析构函数中释放堆空间的内容}			// 自动内存管理的重要手段};int main(int argc,char* ar[])
{Smart_pointer spt(new Test(Sophire));spt->print_name();	// 使用方式与指针相同Test t(*spt);return 0;
}

天马行空,非常巧妙地利用了C中的优秀特性进而实现了智能指针。智能指针是大型C程序中自动内存管理的重要手段,例如Android的framework层就大量使用智能指针,还有Qt平台也提供了QPointer类,STL中也有丰富的智能指针类提供,比如auto_ptr。

上面的智能指针太过专一,问题很大。要是每一个对象都创建一个智能指针类对象来封装,那得多少的代码量,而且绝大部分都是用CTRLC和CTRLV,没什么技术含量啊。Well,是时候引入新技能了-------大名鼎鼎的模板(template),将模板一分为二,各自占山为王,一个叫函数模板,另一个叫类模板,很明显智能指针类毫无疑问是用类模板技术,函数模板下回讲解,现在就对类模板一探究竟吧。。。等等等,等,猛攻不如巧夺,先速来回顾一下有异曲同工之妙的宏定义。


#include <iostream>// 使用宏定义并不需要考虑参数类型
#define Compare(a,b)		\
{				\a > b ? a : b;		\
}				using namespace std;int main(int argc,char* ar[])
{int a = 1;int b = 2;double c = ;double d = 4;int x = Compare(a,b);	    // 可以处理int类型double y = Compare(c,d);    // 可以处理double类型cout << x =  << x << endl;cout << y =  << y << endl;return 0;
}

宏定义天生强大,很多Hackers都倾向于使用宏定义,因为其速度极快,不需要函数调用栈的开销,但是宏的缺点也是致命的,宏定义是由预处理器处理的单元,编译器并不知道宏的存在,所以并不会对其进行语法检查。我们需要的是更安全的方法------模板。直接上代码!

//SmartPointer.h#ifndef _SMARTPOITER_H_
#define _SMARTPOITER_H_template	// 模板技术,代码复用的重要手段
<typename T>	// 泛型编程,使用类模板
class SmartPointer
{
private:	T* mp;	// T代表了使用时指定的类型
public:SmartPointer(T* p = ULL){mp = p;}SmartPointer(ct SmartPointer<T>& obj){mp = p;ct_cast<SmartPointer<T>&>(obj).mp = ULL;}SmartPointer& operator = (ct SmartPointer<T>& obj){if (this != &obj){delete mp;mp = p;ct_cast<SmartPointer<T>&>(obj).mp = ULL;}return *this;}T* operator -> (){return mp;}T& operator * (){return *mp;}T* get(){return mp;}bool isULL(){return (mp == ULL);}~SmartPointer(){delete mp;}
};#endif

类模板中的函数也可以在类外实现,不过同样需要加上模板的声明。此处不做详解。
现在可以来使用类模板了,实践出真知,动手吧!

//#include <iostream>
#include <string>
#include SmartPointer.h	// 包含对应的头文件using namespace std;class Test			// 示例类,可以有多个
{
private:string m_name;
public:Test(ct string name){m_name = name;cout << Hello  << m_name << endl;}Test(ct Test& obj){cout << Test(ct Test& obj) << endl;this->m_name = _name;}void print(){cout << I am  << m_name << endl;}~Test(){cout << Goodbye  << m_name << endl;}
};int main(int argc, char ct *ar[])
{	SmartPointer<Test> pt(new Test(Sophire));  // 在堆空间上创建Test类对象cout << pt =  << pt.get() << endl;  // 调用pt对象中的函数,获取其所占用堆空间的地址pt->print();	// 可以像类指针一样操作cout << endl;SmartPointer<Test> ptt(pt);	// 用刚才的对象初始化新创建的智能指针类对象,发生堆空间使用权力的转移,之前的对象将被置空cout << pt =  << pt.get() << endl;	// 值为 ULLcout << ptt =  << ptt.get() << endl;ptt->print();return 0;
}

学无止境,模板有太多的细节值得去深究,例如,模板有一种特殊的实现,模板的特化,这里面的内容相对深奥,知识点较多,读者有兴趣可以自行查阅资料。

1]:
[2]: /
[]: /
[4]: .js/

#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格

本文地址:http://www.dnpztj.cn/shuma/856929.html

相关标签:无
上传时间: 2024-02-10 03:26:51
留言与评论(共有 10 条评论)
本站网友 中国人保车险
5分钟前 发表
” 这看似简单的一句话,被难倒的初学者不计其数
本站网友 西电e流
24分钟前 发表
智能指针是大型C程序中自动内存管理的重要手段,例如Android的framework层就大量使用智能指针,还有Qt平台也提供了QPointer类,STL中也有丰富的智能指针类提供,比如auto_ptr
本站网友 女厕吧
19分钟前 发表
现在可以来使用类模板了,实践出真知,动手吧! //#include <iostream> #include <string> #include SmartPointer.h // 包含对应的头文件using namespace std;class Test // 示例类,可以有多个 { private
本站网友 lpk
17分钟前 发表
直接上代码! //SmartPointer.h#ifndef _SMARTPOITER_H_ #define _SMARTPOITER_H_template // 模板技术,代码复用的重要手段 <typename T> // 泛型编程,使用类模板 class SmartPointer { private
本站网友 农行深圳分行
18分钟前 发表
1]
本站网友 因为是第一次
7分钟前 发表
等等等,等,猛攻不如巧夺,先速来回顾一下有异曲同工之妙的宏定义
本站网友 北京教育学院
26分钟前 发表
char* ar[]) {int a = 1;int b = 2;double c = ;double d = 4;int x = Compare(a
本站网友 网页错误详细信息
17分钟前 发表
p
本站网友 合肥钟点工
4分钟前 发表
记住一句话就可以了,左数据右地址