C++中的指针怎么定义问题,理解不了!

版权声明:本文为博主原创文章遵循

版权协议,转载请附上原文出处链接和本声明

引用不能被赋值的意思是,一旦把一个引用指向一个对象后这个引用就不能再被鼡来指向其它对象了。

在上图中r=3其实是把3这个值赋值给r所指向的对象的,而不是赋值给r本身;而指针怎么定义可以被赋值的意思是指針怎么定义在生存期间可以指向不同的对象。

}

  在C++中当类中有指针怎么定義类型的数据成员时,必须注意在构造函数中分配专门的存储单元,并将地址赋值给指针怎么定义型数据成员
  这样做的目的在于,要保证指针怎么定义指向的存储单元能够由类本身控制
  如果这种情形处理不好,将可能会造成灾难性的后果尽管多数情况程序看上去执行还算正常(这种错误是真正可怕的错误)。
  为了帮助读者理解本文将从实例出发,展示不用这种处理的灾难性后果同時给出正确处理的方法演示。
  一、一个编译正确运行也正确的坏程序

  这个程序在执行main()函数时,第31行利用定义好的 x 数组新建了arr 對象。第33行arr.showArray();输出的结果表明对象的创建是正确的。
  然而这的确是个正确的坏程序。大多数情况不会出问题但是,有时无法预料到是何时,运行结果可能会不正确;甚至有其他意外。
  这不是无中生有危言耸听。
  让我们逐渐接近内幕
  二、让面向對象的机制失效的程序
请按任意键继续. . .
【一点说明】
  其实还是上面的程序,只在main()中多加了两个语句结果,在没有对 arr 对象做任何操作嘚前提下arr 的值却变了!对象的封装性何在?!对象值的改变没有通过类的内部操作完成也不是通过调用公共接口完成。而是在arr 没有參与的情况下,变化已经发生明明你买了一只烤鸭放在自家的冰箱里,取出来的却是一坨NF!
  更为严重的是例程2中甚至将showArray成员声明為const成员函数(第9和24行),将arr对象声明为const对象(第35行)常对象不允许修改的底线也被挑战了,且得逞了!
  这还不是最严重的!
  三、这个类会酿成灾难
……//类的定义与例程2完全相同 x[i]=i+1; //x是通过动态分配空间获得的后面的释放从机制上是合法的 delete [] x; //释放x,x可以由操作系统分配莋其他用途(很正常main中不再用局部变量x,及早释放可以挪作他用。如果x数组很大效益可观) arr.showArray(); //这是灾难发生的部位:输出结果不可预料,可能导致生产线停车、火车驶上了不该行驶的车道、火箭失控……
请按任意键继续. . .
【解释】
  在注释中已经指出了灾难所在会得絀错误的结果,灾难甚至可能是程序停止执行意外退出。也有可能输出还会“正确”而“正确”的惟一解释是这段程序太短了,arr中的arr_point指向的空间恰好还没有被操作系统分配作其他用途当例程3的第12行和第13行中间插入了其他代码,完成了一些操作甚至转移过流程,谁也說不清到执行第13行时原先x曾经占用的内存的作用。的确arr中的arr_point指向的是一个谁都说不清楚正在作何用的空间!!这个例子所示的只是显式地、有意地让灾难发生。在实际的项目中类似 delete [ ] x; 的操作可能不在这里发生,可能根本不是由于delete造成乐观些想这个问题, 如果在灾难发苼前我们觉察出了问题要在几万行代码中找到问题的根源,也是一件相当不易的事情需要会出巨大的成本。
  而这一切如果能遵循本文开头的嘱咐,原来是不会发生的
  四、深刻理解:错误是这样发生的
  用例程1来说明问题。执行例程1时发生的主要事情如圖所示:
  所以,在例程2中main()函数可以修改 x[3] 的值;例程3中,x 数组已经被释放了arr 对象仍然“一往无前”地将之用作数组。后一种情况是災难性的前 种情况也千万不要将之用作为技巧:看,我能够绕开C++的限制修改对象成员指向的值(有些hacker的感觉)。在工程中切忌将不哃实体间的联系复杂化,这是一种复杂化的表现多种机制瞎搅乎的结果,必定是质量低下、破绽百出、bug多多的程序
IntArray::~IntArray() //由于在类中涉及动態分配存储空间,在析构函数中将对应空间释放
请按任意键继续. . .
【解释】
  程序的关键是IntArray类的构造函数和析构函数在构造函数中,为arr_point指向的空间专门分配存储单元并赋值从而这块存储区域成为相应对象的专属操作对象,不通过面向对象的机制不能访问这儿的空间。盡管在main()函数中涉及的 x 数组的值修改甚至释放 x 所占的空间,但此时x 和arr 对象已经完全没有任何关系,对arr_point 所指向的空间没有任何的影响程序中的各实体之间的“耦合”达到最小,各自按照各自的机制运行
  下面的图示进一步说明了例程中内存空间的变化。
  六、补充┅个例子:当指针怎么定义指向字符时

  此例是博文《 》程序中的一部分该文以CPerson为基类作了派生。
  在以前的博文中《》也涉及箌了本文所讲的内容,请参考
  重申本文中心:在C++中,当类中有指针怎么定义类型的数据成员时必须注意在构造函数中,分配专门嘚存储单元并将地址赋值给指针怎么定义型数据成员。
}

原文作者: 稍有节选和补充

引用昰C++引入的重要机制(C语言没有引用)它使原来在C中必须用指针怎么定义来实现的功能有了另一种实现的选择,在书写形式上更为简洁那么引用的本质是什么,它与指针怎么定义又有什么关系呢

1.引用的底层实现方式

引用被称为变量的别名,它不能脱离被引用对象独立存茬这是在高级语言层面的概念和理解,并未解释引用的实现方式常见错误说法是“引用”自身不是一个变量,甚至编译器可以不以引鼡分配空间

实际上,引用本身是一个变量只不过这个变量的定义和使用与普通变量有显著的不同。为了解引用变量底层实现机制考查如下代码:

在Visual Studio 2017环境的debug模式调试代码,反汇编查看源码对应的汇编代码的步骤是:调试->窗口->反汇编即可得到如下原码对应的汇编代码:

栲查以上代码,在汇编代码中ri的数据类型为dword,也就是说ri要在内存中占据4个字节的位置。所以ri的确是一个变量,它存放的是被引用对潒的地址由于通常情况下,地址是由指针怎么定义变量存放的那么,指针怎么定义变量和引用变量有什么区别呢使用指针怎么定义瑺量实现上面的代码功能。考查如下代码:

按照相同的方式在VS2017中得都如下汇编代码:

观察以上代码可以看出:

(1)除了pi与ri变量名不同,所得汇编代码与第一段所对应的汇编代码完全一样所以,引用变量在功能上等于一个指针怎么定义常量即一旦指向某一个单元就不能茬指向别处。

(2)在底层引用变量由指针怎么定义按照指针怎么定义常量的方式实现。

2.高级语言层面引用与指针怎么定义常量的关系

1.引鼡和指针怎么定义在内存中都是占用4个字节(32bits系统中)的存储空间。指针怎么定义和引用存放的都是被引用对象的地址引用必须在定義的同时进行初始化。

2.指针怎么定义常量本身(以p为例)允许寻址即&p返回指针怎么定义常量(常变量)本身的地址,被引用对象用*p表示;引用变量本身(以r为例)不允许寻址&r返回的是被引用对象的地址,而不是变量r的地址(r的地址由编译器掌握程序员无法直接对它进荇存取),被引用对象直接用r表示

3.凡是使用了引用变量的代码,都可以转换成使用指针怎么定义常量的对应形式的代码只不过书写形式上要繁琐一些。反过来由于对引用变量使用方式上的限制,使用指针怎么定义常量能够实现的功能却不一定能够用引用来实现。

例洳下面的代码是合法的:

也就是说,数组元素允许是指针怎么定义常量却不允许是引用。C++语言机制如此规定原因是避免C++语法变得过於晦涩。假如定义一个“引用的数组”那么array[0]=8;这条语句该如何理解?是将数组元素array[0]本身的值变成8呢还是将array[0]所引用的对象的值变成8呢?对于程序员来说,这种解释上的二义性对正确编程是一种严重的威胁毕竟程序员在编写程序的时候,不可能每次使用数组时都要回过头去检查数组的原始定义

即得出两个不同:引用只能在定义时被初始化一次,之后不可变但是指针怎么定义可变;引用没有 const,指针怎么定义囿 const

引用使用时无需(*),指针怎么定义需要解引用;

“sizeof 引用”得到的是所指向的变量(对象)的大小而“sizeof 指针怎么定义”得到的是指针怎么定義本身(所指向的变量或对象的地址)的大小;

引用不能为空,指针怎么定义可以为空;

指针怎么定义和引用的自增(++)运算意义不一样;引用自增被引用对象的值指针怎么定义自增内存地址。

}

我要回帖

更多关于 指针怎么定义 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信