C++快速入门 (四) 引用 和 指针
2012-12-26 12:16
369 查看
一. 引用
(1). 内存中变量的存储
前边说过 计算机管理内存时,会以字节为基本单位进行顺序线性格式化(x86保护模式下),这样每一字节的内存都会有一个独一无二的十六进制数字标识, 定义一个变量的过程 其底层就是将 变量的值写入某个数字标识符所代表的内存的过程。如int a = 10;
变量名 a 实质上只是为了方便编程而由 编程语言机制 附加的功能,当代码编译为机器码时,变量名是不存在的, 只是用其地址值和其长度来表示。例如 变量 a 被存储在 地址 0x001efd1c (起始地址) , 而数据类型 int 编译时会被转换为其代表的变量长度4字节(32位处理器) ,
说了这么多,其实只是想说明 C++每个对象都有一个内存地址值, 地址值所指向的内存+加其长度所对应的内存块保存着对象的值, 比如上边的 a 的地址值是 0x001efd1c, (0x001efd1c+4)这块内存保存了
a 的值 10
(2). 引用
C++中 可以使用 符号 <&> 来声明引用[align=left] int a = 10;[/align]
[align=left] int &ay = a;[/align]
这时 ay本身对应的内存空间 将保存 一个地址值 ,该地址值指向 变量 a内存空间 的 地址。既
ay -> ay的内存地址 -> a的变量值地址 -> a的值 10
在 C++ 中是无法获取引用本身的内存地址,而是返回其内存地址中存储的指向 a 的 变量值 的地址 .
(3). 引用的特性,
创建时必须要被初始化一旦创建后指向一个对象地址就不能改变
不能有 NULL 引用。
[align=left] int k=10,y=20;[/align]
[align=left] int &a = k; [/align]
[align=left] cout << &a << endl;[/align]
[align=left] a = y;[/align]
[align=left] cout << &a << endl; // 引用地址相同[/align]
[align=left] cout << a << endl;[/align]
从上边的代码可以看出, 引用一旦定义,就不能改变其引用的对象地址, 只能改变引用对象本身,
二. 指针
(1). 什么是指针
可以看到 引用的最大特性既 一旦定义就不能修改地址使其指向另一个对象,而指针 就没有这种限制,指针,则既可以改变指针指向的对象地址,也可以改变指针指向对象的本身C++中 符号 <*> 来声明指针
int a = 10;
int *p = &a;
可以看到 , 必须要使用对象的地址为指针赋值, &a 就表示获取 a 的内存地址, 有些书上会把当前应用下的符号 <&> 叫 取地址操作符,
(2). 指针的特性:
指针是一种类型指针所指向的对象地址是可以更改的
特殊指针void 可以指向任何类型
(3). 指针的使用
只定义一个指针显然是没有意义的,实用才是硬道理, 一般的对指针类型可以进行三种操作获取指针本身的地址
获取指针所指向的对象地址
获取指针所指向的对象
(4). 获取指针本身的地址
可以使用 使用 取地址符 <&>来获取 指针本身的地址int a = 10;
int *p = &a;
cout << &p; //获取指针本身的地址
(5). 获取指针所指向的对象地址
指针本身保存的就是指向对象的地址,所以可以直接获得int a = 10;
int *p = &a;
cout << p; //获取指针指向对象的地址
(6). 获取指针所指向的对象
对已定义的指针使用符号 <*>,就可以获取其指向的对象,在该应用场景下 符号 <*>通常被叫做解引用操作符int a = 10;
int *p = &a;
cout << *p; //获取指针所指向的对象 输出 10
当需要访问指针所指向对象的内部类型或函数时,C++中 还有一种 解引用操作符 < -> > , 如下代码, 通过指针访问自定义类型 TT 的 共有变量 tem
[align=left]class TT[/align]
[align=left]{[/align]
[align=left]public :[/align]
[align=left] TT(int x =0):tem( x ){};[/align]
[align=left] int tem;[/align]
[align=left]};[/align]
[align=left]int _tmain (int argc, _TCHAR* argv [])[/align]
[align=left]{[/align]
[align=left] TT *p = new TT(10);[/align]
[align=left] cout << (p->tem) << endl; // return 10[/align]
[align=left] return 0;[/align]
[align=left]}[/align]
(7). 指针的指针
我们可以让一个指针指向另一个指针,听着就很蛋疼,但是的确可以这样做,[align=left] int a = 10;[/align]
[align=left] int *p = &a;[/align]
[align=left] int **pv = &p; // **pv == *(*pv)[/align]
[align=left] cout << *pv << endl;[/align]
[align=left] cout << **pv << endl; // **pv == *(*pv)[/align]
传递给指针的指针 是 指针本身的地址,要输出指针的指针指向的对象,理所应当进行2次解引用操作
你可以按照该规则继续定义 指针的指针的指针,指针的指针的。。。
三 指针 和 const
(1). 使什么 const
通过前面我们知道,要改变指针的值 可以通过改变指针所指向的地址 或 改变指针所地址指向的对象 两种方式实现, 要将一个指针设置为常量,就得从这两个途径下手, 于是 C++ 为这两种方式都提供了 const 语法, 你也可以将这两种 const语法 同时使用在一个指针类型上, 使其成为真正的常量 (2). 三种 const 指针类型下边这段有点绕~
指向 常量( 指针指向的对象是常量 ) 的非常量指针(指针本身不是常量) , 不能通过该指针修改对象的值, 但可以修改该指针指向的地址
[align=left] int a = 10, b = 20;[/align]
int const *p = &a; // const int *p
= &a; 两种写法是等价的
[align=left] p = &b;[/align]
[align=left] (*p) = 30; // error[/align]
指向非常量( 指针指向的对象可更改 ) 的常量指针(指针本身不能更改), 这东东很像引用 -- 可以修改该指针指向对象的值,但不能修改指针指向地址 声明方式:
[align=left] int a = 10, b = 20;[/align]
[align=left] int *const p = &a;[/align]
[align=left] p = &b; //error[/align]
[align=left] (*p) = 30; [/align]
指向常量的常量指针, 这个比较好理解,不能修改指针也不能通过该指针修改其指向对象的值, 声明方式:const int *const p3 = &a;
[align=left] int a = 10, b = 20;[/align]
[align=left] const int *const p = &a;[/align]
[align=left] p = &b; //error[/align]
[align=left] (*p) = 30; //error[/align]
简单理解就是: 当const前有星号时, 表示指针地址不能修改, 当const前无星号时,则指针当前对象值不能修改,既 有星号锁地址 , 无星号锁对象,两个const真常量 示例如下
[align=left] int a = 10,b = 20;[/align]
[align=left] // 指向常量的 非常量指针[/align]
[align=left] int const *p1;// 不能通过 指针p1修改对象[/align]
[align=left] // *p1 = b; 错误的 不能通过该指针p1 来修改对象[/align]
[align=left] p1 = &b; // ok 但是可以改变当前指针指向的地址[/align]
[align=left] cout << *p1 << endl; // 20[/align]
[align=left] // 指向非常量的 常量指针[/align]
[align=left] // 很像引用 -- 可以修改指针指向的对象,但不能修改指针指向的地址[/align]
[align=left] int *const p2 = &a; //初始化是必须定义对象[/align]
[align=left] // p2 = &b; 错误的 不能修改其指向的地址[/align]
[align=left] *p2 = b; //ok 使用b的值 修改对象a的当前值[/align]
[align=left] cout << &a << " | " << p2 << endl; // 相等[/align]
[align=left] cout << *p2 << endl; // 20[/align]
[align=left] //指向常量数据的常量指针[/align]
[align=left] const int *const p3 = &a; //初始化时声明对象[/align]
[align=left] // p3 = &b; // 错误的[/align]
[align=left] // *p3 = b // 错误的[/align]
[align=left] a = 30;[/align]
[align=left] cout << *p3 << endl; // 30[/align]
(2). "不靠谱"的 引用/指针 常量
引用和指针声明为const,也只能表示通过自身不能更改对象,而不能保证对象一定不能被更改, 这是由于引用和指针都是保存对象的地址,当另一个指向该地址的变量非 const 并更改时, 很显然 只是保存该对象地址的 引用和指针的值也会更改[align=left] int x = 10;[/align]
[align=left] const int &y = x;[/align]
[align=left] x = 30;[/align]
[align=left] cout << y << endl; // 30[/align]
[align=left] int a = 10;[/align]
[align=left] const int *const p = &a;[/align]
[align=left] a = 30;[/align]
[align=left] cout << *p << endl; // 30[/align]
四. 本质
(1). 引用和指针的本质
从语言级来说指针和引用差别还是很大的,上边都已经叙述过了,但从底层实现上来说不管是引用还是指针, 其实质都如下图![](http://img.my.csdn.net/uploads/201212/26/1356495565_8728.png)
引用或指针本身都会占用4字节空间( 32位处理器 ) ,而自身的地址空间保存着指向某个对象的内存地址值。而不是对象本身, 举个例子来说,像使用手机打电话, 首先要在手机(指针)里输入电话号码(将对象地址存入指针地址), 然后接通(通过指针里存储的对象地址找到所指向的对象)。当我们要联系另外其他人时,只需换一个号码接通就可以,而不是换一个手机 , 不管指针还是引用 其底层实现都是这么个过程。
-
<原创文章 转载请注明出处 http://blog.csdn.net/meiwm 谢谢>
作者:meiwm
出处:http://blog.csdn.net/meiwm
本文为原创,本文版权归作者所有。欢迎转载,但请务必保留此段声明,且在文章页面明显位置给出原文连接,谢谢合作。
-
相关文章推荐
- C++入门篇之值传递,指针传递和引用传递的那些事
- 《算法笔记》2.7小节——C/C++快速入门->指针
- 快速入门C++ 04(传值、传址传引用)
- C++快速入门 (七) 再谈指针和函数
- c++快速简易入门教程_009引用
- 《算法笔记》2.7小节——C/C++快速入门->指针
- c++快速简易入门教程_005this指针
- 《算法笔记》2.7小节——C/C++快速入门->指针
- 《算法笔记》2.7小节——C/C++快速入门->指针
- 传值、传值和传引用 - C++快速入门12
- this指针和类的继承 - C++快速入门16
- 传值、传值和传引用 - C++快速入门12
- this指针和类的继承 - C++快速入门16
- C++引用与指针的比较
- C++文本查询程序 定义类管理数据 用引用共享数据 不用智能指针 C++Primer练习12.27
- C++指针入门(一)
- C++中引用与指针有什么区别
- 浅谈C++中指针和引用的区别
- 详解c++指针的指针和指针的引用
- C++复合类型--引用和指针