= 符在C/C++里是最常见也最基本的操作符,通常解释为赋值,流程表达为←,即将符号右边的内容替换左边的内容。
然而,对于指针操作而言,= 符与其说成是赋值不如改称重定向更合适:因为赋值语义的限定性包含了变更与复制内容两个相似而行为相左的概念,使得很多初学者乃至一些有经验的编程人员都会落入指针操作陷阱,从而被一些不了解C/C++的人极力攻讦的对象。而这主要原因来自于早期引进翻译的人本身的认知局限,其后语言学家们不究明里的一味跟风所致(国外原版也好不到哪里,幸亏数学表达一直用←而不是含≌性质的<=)。
←指向是将目标地址直接替代原有地址,使新得到的数据与目标完全
同一,即两者是不分彼此的关联关系,是一个对象。
<=复制则是在
原空间内填写目标数据内的内容,对指针而言,原指针指向性不变,但指向的地址内容发生了变化,变化值与目标相同,左值与右值依然是两个独立存在的对象,相互间是全等关系。
←与<=的区别在哪呢?对于简单类型来说,没有任何的不同,当左值变更为右值时,其空间的实际情况也同时被复制成右值数据,因此说成赋值一点也不为过。但对指针或复杂类型而言,赋值一说就显得宽泛不严谨了。也就是许多人说的深拷贝浅拷贝问题。
在指针上,←是指指针定向,注意这里不包括复制功能!也就是说,当发生←操作时,原有的指向空间将会被新的地址所取代,从而实现左值与右值相同都指向同一地址情况,达到数据快速定位、调度、运算的目的。但是,毕竟是指针重定向,其原来指向的空间将因为没有指针管理回收而成为野指针,最终造成系统资源泄露,这也是许多人诟病指针难学的原因。通常意义上讲,很多使用指针赋值的人,大多会习惯性的认为 = 操作会令系统替其完成复制数据功能,从而依赖系统自动的做一些本来就应该是编程者做的事,而实际上系统远不会那么“智能”,这种情况下程序出错也就在所难免。
为了实现这种使用 = 作指针及复杂类型复制操作,有些“大能”想到了操作符重载,可这又是另一个陷阱:性能及资源循环。
其实,了解到了指针 = 的指向性,完全可以简化很多程序操作,大可以直接使用指针对所指向的对象进行操作,当且仅当需要产生与原对象独立的对象时才使用复制建立对象,如果完全遵循这个原则,将极大的杜绝内存泄露与野指针、垃圾数据问题。由此,也就可以理解,C语言为什么有那么多字符串、内存的复制函数了。
相关举例如下:
struct T{
Type a;
}
T fun(){
T a;
...
return a; //---- a 解析,内容不确定
}
T t1=fun() //----- 垃圾数据读取
T* fun1(T *a)
{
...
return a;
}
T fun2(T& a)
{
...
return a;
}
t1 = *(fun1(&a));
t1 = fun2(a);
T* f1()
{
T *a=0;
a = new T;
...
return a; //------ 不建议采用的指针创建,如无接受对象将引发资源问题,此种函数适用于初始化指针变量
}
T* f1(T **a)
{
if(!*a)
*a = new T;
...
return *a;
}
T* f2(T* &a)
{
T *t=0;
try{
t = new T;
}catch(...){goto Done;}
...
if(a){
delete a;}
a = t;
t = 0;
Done:
if(t)delete t;
return a;
}
T *t2=0;
f1 (&t2);
t2 = f1(&t2);
f2(t2);
t2 = f2(t2);