博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

范磊 C++ 第8章 指针

Posted on 2014-10-10 23:31  六年一班刘同学  阅读(239)  评论(0编辑  收藏  举报
  1 // section_8.cpp : Defines the entry point for the console application.
  2 //范磊 C++ 第8章 指针
  3 //指针本质也是一个变量,只是这个变量存放的数据比较特殊,怎么特殊?
  4 //里面存放的是别人家的地址. 其他变量的内存编号而已.
  5 
  6 #include "stdafx.h"
  7 #include "iostream"
  8 
  9 using namespace std;
 10 
 11 //--------------------------------------------------
 12 //8.1 地址
 13 //地址,可以理解为:每一个内存都有自己的空间编号,这个编号称为"地址"
 14 void fun1()
 15 {
 16     int i;
 17 
 18     i = 1;
 19     cout << &i << endl ;    // &是取地址符号,在变量名字前面 +&,表示获得这个变量 i 的内存编号.
 20 }                            //c++直接回输出一个16进制的数字.不向c那样,前面要 %x 表示16进制.
 21 
 22 
 23 //--------------------------------------------------
 24 //8.2 用指针来保存地址
 25 //用一个特别的变量(指针)去存放其他变量的内存地址.
 26 void fun2()
 27 {
 28     int a;
 29     int* p;
 30 
 31     p = &a;
 32     cout << &a << endl;        //打印出变量a的地址 0018ffe0
 33     cout << p << endl;        //打印出变量a的地址 0018ffe0,所以说指针p 保存了变量a的地址.
 34 }
 35 
 36 
 37 //-------------------------------------------------
 38 //8.21 空指针(好像不是很适合叫空指针)
 39 //当我们定义了一个指针后,如果不初始化,这个"迷途指针"里面的内容是一个随机数
 40 //所以我们要给指针赋值,赋个0给他.
 41 void fun3()
 42 {
 43     int* p;
 44     p = 0;
 45     cout << "p: " << p << endl;
 46 }
 47 
 48 
 49 //-------------------------------------------------
 50 //8.2.3 用指针来访问值
 51 // 符号 * 称为指针运算符. 意思是取出指针里面的地址的内容.
 52 //例如 指针p = 1234567 ,*p 的意思就是 取出内存地址单元编号为1234567 里面的内容.
 53 //汇编理解:  mov Exr, ds:[1234567]
 54 void fun4()
 55 {
 56     int a;
 57     int* p;
 58 
 59     a = 1;
 60     p = &a;
 61 
 62     cout << "&a的值为:" << "\t" << &a << endl ;
 63     cout << "a的值为:" << "\t"  << a << endl ;
 64     cout << "p的值为:" << "\t"  << p << endl ;
 65     cout << "*p的值为:" << "\t"  << *p << endl;
 66 }
 67 //打印的结构是 a == 1 , *p == 1.  
 68 
 69 
 70 //-------------------------------------------------
 71 //8.2.4 指针地址,指针保存的地址和该地址的值
 72 //指针的地址: 因为指针的本质其实也是一个变量,这个变量肯定占用内存空间,肯定有内存单元编号
 73 //指针保存的地址:指针里面存放的数据,这个数据不是一般普通数据,这个数据是其他内存的单元编号(地址).
 74 //该地址的值:可以通过指针里面的地址,按照地址去找到那个内存,看看里面放的是什么数据.
 75 void fun5()
 76 {
 77     int i;
 78     int* p;
 79 
 80     cout << "i的地址为: " << &i << endl ;
 81     cout << "p的值为: " << p << endl ;        //此时p还没赋值,属于一个"迷途指针"
 82     cout << "p的地址为: " << &p << endl ;    //p虽然是迷途指针,但前面已经进行int* p 声明了.
 83                                             //所以p也有自己的地址.
 84     i = 3;
 85     cout << "i赋值后的地址为: " << &i << endl ;
 86 
 87     p = &i;                                        //把 i 的地址告诉了p.
 88     cout << "p赋值后的值为: " << p << endl ;    //p里面存放就是i的地址.
 89     cout << "p赋值后的地址为: " << &p << endl ;
 90 
 91 }
 92 
 93 
 94 //-------------------------------------------------
 95 //8.2.5 指针对数值的操作
 96 //可以通过 * 号,间接访问或读取指针的保存的地址里面的数据
 97 typedef unsigned short int ut;    //因为unsigned short int 这个类型名字很长,另外起了个小名 ut
 98 void fun6()
 99 {
100     //cout << sizeof(ut) << endl ;    //测试一下ut是占用了多大内存空间
101     ut i;
102     ut* p = 0;
103     
104     i = 5;
105     p = &i;        //自从当执行p = &i以后, 改变了*p就是改变了i,改变了i就是改变了*p
106 
107     cout << "i = " << i << endl ;
108     cout << "*p = " << *p << endl;
109 
110     cout << "用指针来修改存放在i中的数据...\n"  ;
111     *p = 90;
112     cout << "i = " << i << endl ;
113     cout << "*p = " << *p << endl;
114 
115     cout << "用i来修改存放在i中的数据...\n"  ;
116     i = 9;
117     cout << "i = " << i << endl ;
118     cout << "*p = " << *p << endl;
119 }
120 
121 
122 //-------------------------------------------------
123 //8.2.6 更换指针保存的地址
124 //平时,小明口袋里放着怎么去小芳家的地图,所以他只知道小芳家有什么东西.
125 //今天他口袋了放的是去小李家的地图,所以他只知道小李家有什么东西.不知道小芳家有什么东西.
126 void fun7()
127 {
128     int i;
129     int j;
130     int* p;
131     
132     i = 10;
133     j = 20;
134     p = &i;        //p存放着的是i的地址,所以p知道i里面有什么东西.
135 
136     cout << "i:" << "\t" << i <<endl ;
137     cout << "&i:" << "\t" << &i << endl ;
138     cout << "j:" << "\t" << j <<endl ;
139     cout << "&j:" << "\t" << &j << endl ;
140     cout << "p:" << "\t" << p <<endl ;
141     cout << "*p:" << "\t" << *p << endl ;    //*p获得就是i的内存里面的内容.
142 
143     p = &j;        //p存放着的是j的地址,所以p知道j里面有什么东西.
144 
145     cout << "更换地址后...\n" ;
146     cout << "i:" << "\t" << i <<endl ;
147     cout << "&i:" << "\t" << &i << endl ;
148     cout << "j:" << "\t" << j <<endl ;
149     cout << "&j:" << "\t" << &j << endl ;
150     cout << "p:" << "\t" << p <<endl ;
151     cout << "*p:" << "\t" << *p << endl ;    //*p获得就是j的内存里面的内容.
152 }
153 
154 
155 //-------------------------------------------------
156 //8.3.2 用指针创建堆中空间
157 //什么叫堆?(3个特点):1.堆是一大堆不连续的内存区域;2.堆生存的时间要比栈长;3.堆要手动申请,手动释放;
158 //C++中,用关键字 new 创建一个堆,并分配内存.
159 void fun8()
160 {
161     int* p;
162     p = new int; //这里如果直接写 new int 是不会报错的,但不能运行.为什么?
163                  //堆是一大堆大小不连续的内存区域,在系统中由链表串接起来使用,堆中的每个内存单元都是
164                  //匿名的,因此必须先在对堆中申请一个内存单元地址,然后保存在一个指针中,只有使用该指针
165                  //才能访问到该内存单元的数据.
166     *p = 4;
167     cout << *p << endl ;            //堆的内容
168     cout << "p: " << p << endl;        //堆的地址
169     cout << "&p: " << &p << endl;   
170 }
171 //函数的框架是esp-48h,多了的8个字节是怎么来?
172 //int* p 这里多了4个字节. 另外是 new int 这里也多了4个字节.
173 
174 
175 //-------------------------------------------------
176 //8.3.3 用指针删除堆中空间(成也萧何败也萧何)
177 //C++中,用关键字 delete 释放堆的空间.否则的话,会造成内存泄露.
178 //什么叫内存泄露?
179 //堆的地址一定是在指针里面的,只有指针才知道怎么去找到堆.如果指针丢了,那么其他任何途径都找不到这个堆了.
180 //一个宝藏地图只有小明知道,但是小明死了,其他人永远也别想找到宝藏的位置了.
181 void fun9()
182 {
183     int* p;
184     p = new int;
185     *p = 3600;
186 
187     cout << *p << endl ;
188 
189     delete p;
190     cout << *p << endl ;    //p已经变成了迷途指针了.
191 
192     p = 0;
193     p = new int;
194     *p = 8;
195     cout << *p << endl ;
196     
197     delete p;
198     cout << *p << endl ;
199 }
200 
201 
202 //-------------------------------------------------
203 //8.4.2 在堆中删除对象
204 class A
205 {
206 private:
207     int i;
208 public:
209     A()
210     {
211         cout << "构造函数执行中...\n" ;
212         i = 0x999;
213     }
214     ~A()
215     {
216         cout << "析构造函数执行中...\n" ;
217     }
218     int get()
219     {
220         return i;
221     }
222 };
223 void fun10()
224 {
225     A* p;
226     p = new A;
227     delete p;
228 }
229 //函数框架不明白.
230 
231 
232 
233 //-------------------------------------------------
234 //8.4.4 访问对中的数据成员
235 //必须要通过指针才能访问堆.
236 class A1
237 {
238 private:
239     int i;
240 public:
241     int get() const
242     {
243         return i;
244     }
245     void set(int x)
246     {
247         i = x;
248     }
249 };
250 void fun11()
251 {
252     A1* a;
253     a = new A1;
254     a->set(66);        //通过 -> 符号来访问堆.
255     cout << a->get() << endl ;
256     delete a;
257 }
258 
259 
260 //-------------------------------------------------
261 //8.4.5 在构造函数中开辟内存空间
262 class A2
263 {
264 private:
265     int* i;
266 public:
267     A2();
268     ~A2();
269     int get() const
270     {
271         return *i;
272     }
273     void set(int x)
274     {
275         *i = x;
276     }
277 };
278 void fun12()
279 {
280     A2* p;
281     p = new A2;
282     cout << p->get() << endl ;
283     p->set(0) ;
284     cout << p->get() << endl ;
285     delete p ;
286 }
287 A2::A2()
288 {
289     cout << "构造函数执行中... \n" ;
290     i = new int(999) ;
291 }
292 A2::~A2()
293 {
294     cout << "析构函数执行中... \n" ;
295     delete i ;
296 }
297 
298 
299 //-------------------------------------------------
300 //8.4.6 对象在栈与堆中的不同
301 class A3
302 {
303 private:
304     int* i;
305 public:
306     A3();
307     ~A3();
308     int get() const    //const加在这里什么意思?
309     {
310         return *i;
311     }
312     void set(int x)
313     {
314         *i = x;
315     }
316 };
317 void fun13()
318 {
319     A3* p;
320     p = new A3;        //开辟新的内存空间,空间的首地址放到了p里面.?
321     cout << p->get() << endl ;
322     p->set(123);
323     cout << p->get() << endl ; 
324 }
325 A3::A3()
326 {
327     cout << "构造函数执行中... \n" ;
328     i = new int(999) ;
329 }
330 A3::~A3()
331 {
332     cout << "析构函数执行中... \n" ;
333     delete i ;
334 }
335 
336 
337 //-------------------------------------------------
338 //8.5 this指针
339 //this指针记录每个对象的内存地址,然后通过间接引用符 -> 访问该对象的成员.
340 class A4
341 {
342 private:
343     int i;
344 public:
345     int get() const
346     {
347         return i;
348     }
349     void set(int x)
350     {
351         this-> i;
352         i = x;
353         cout << "this变量保存的内存地址: \t" << this << endl ;
354     }
355 };
356 
357 void fun14()
358 {
359     A4 a;
360     a.set(99);
361     cout << "对象a的内存地址: \t\t" << &a << endl;
362     cout << a.get() << endl;
363 
364     A4 b;
365     b.set(9999);
366     cout << "对象b的内存地址: \t\t" << &b << endl;
367     cout << b.get() << endl;
368 
369 }
370 
371 
372 
373 //-------------------------------------------------
374 //8.6 指针的常见错误
375 //删除一个指针后,一定要将该指针设定为赋值为0.因为删除该指针只会释放它指向的内存空间,不会删除指针.
376 //因此这个指针还存在,并且仍会指向原来的内存空间,这时如果再次尝试使用该指针,将导致程序出错.
377 void fun15()
378 {
379     int* p;
380     p = new int;
381     *p =3;
382 
383     cout << "将3赋值给p的地址后,指针p读取的值: \t" << *p << endl ;
384     delete p;
385     cout << "删除空间后,指针p读取的值: \t\t" << *p << endl ;
386 
387     long* p1;
388     p1 = new long;
389     cout << "创建新空间后,指针p中的保存地址: \t " << p << endl;
390     *p1 = 99999;
391     cout << "指向新空间的指针p1保存的地址: \t\t" << p1 << endl;
392     *p = 23;
393     cout << "将23赋值给p的地址后,指针p读取的值: \t" << *p << endl;
394     cout << "将23赋值给p的地址后,指针p1读取的值: \t" << *p1 << endl;
395     delete p1;
396 }
397 
398 
399 //-------------------------------------------------
400 //8.7.1 指针的加减运算
401 void fun16()
402 {
403     int* p;
404     p = new int;
405     cout << "指针p保存的空间地址为: \t" << p << endl ;
406     p++;
407     cout << "自加后,指针p保存的空间地址为: " << p << endl ;
408     p--;
409     cout << "自减后,指针p保存的空间地址为: " << p << endl ;
410     p -= 2;
411     cout << "减2后,指针p保存的空间地址为: " << p << endl ;    
412 }
413 
414 
415 
416 //-------------------------------------------------
417 //8.7.2 指针的赋值运算
418 void fun17()
419 {
420     int* p;
421     p = new int;
422     cout << "p:" << p << endl;
423     int* p1;
424     p1 = new int;
425     cout << "p1:" << p1 << endl;
426     p = p1;
427     cout << "赋值后...\n" ;
428     cout << "p:" << p << endl;
429 }
430 
431 
432 //-------------------------------------------------
433 //8.7.3 指针的相减运算
434 void fun18()
435 {
436     int* p;
437     p = new int;
438     cout << "p:" << p << endl;
439     int* p1;
440     p1 = new int;
441     cout << "p1:" << p1 << endl ;
442     *p = p - p1;    //两个地址相减,得出的是一个数字.
443     cout << "两个内存的地址差: " ;
444     cout << *p << endl;
445 }
446 
447 
448 
449 //-------------------------------------------------
450 //8.7.4 指针的比较运算
451 void fun19()
452 {
453     int* p;
454     p = new int;
455     cout << "p:" << p << endl ;
456     int *p1;
457     p1 = new int;
458     cout << "p1:" << p1 << endl ;
459     if(p > p1)
460     {
461         cout << "p大于p1的内存地址. \n" ;
462     }
463     else
464     {
465         cout << "p1大于p的内存地址. \n" ;
466     }
467 
468 }
469 
470 
471 //-------------------------------------------------
472 //8.8.1 常量指针
473 //常量指针:指针的值不能改变. 这个指针是一个常量,是一个不变量.
474 class A5
475 {
476 private:
477     int i;
478 public:
479     int get() const
480     {
481         return i;
482     }
483     void set(int x)
484     {
485         i = x;
486     }
487 };
488 void fun20()
489 {
490     A5* p;
491     p = new A5;
492     cout << "p:" << p << endl ;
493     p += 1;
494     cout << "p:" << p << endl ;
495 
496     A5* const p1 = new A5;    //error C2734: 'p1' : const object must be initialized if not extern
497     //p1 = new A5;   不能再这样写了.报上面的错.
498     //p1 += 1;        //因为前面const p1说明了p1是不能改变的.如果非要执行这句的话,编译出错.
499     p1->set(6);
500     cout << p1->get() << endl;
501 
502 }
503 
504 
505 
506 //-------------------------------------------------
507 //8.8.2 指向常量的指针
508 class A6
509 {
510 private:
511     int i;
512 public:
513     int get() const
514     {
515         return i;
516     }
517     void set(int x)
518     {
519         i = x;
520     }
521 };
522 void fun21()
523 {
524     const A6* p;    // const(A6* p) ,说明这个(A6* p)的值是一个常量.
525     p = new A6;
526     p += 1;            
527     //p->set(11);
528     cout << p->get() << endl ;
529 }
530 
531 
532 //-------------------------------------------------
533 //8.8.3 指向常量的常指针
534 class A7
535 {
536 private:
537     int i;
538 public:
539     int get() const
540     {
541         return i;
542     }
543     void set(int x)
544     {
545         i = x;
546     }
547 };
548 void fun22()
549 {
550     const A7*  const p = new A7;      //'p' : const object must be initialized if not extern
551     //p = new A7;          //不能这样写了.
552     //p += 1;              //因为指针是常量,所以这里要进行指针改变,不能通过编译.
553     //p->set(11);          //因为指针指向的内容页是常量,所以这里要进行修改,也不能通过编译.
554     cout << p->get() << endl ;
555 }
556 
557 
558 //////////////////////第8章主要例子完毕///////////////////////
559 
560 
561 int main(int argc, char* argv[])
562 {
563     //fun1();        //8.1 地址
564     //fun2();        //8.2 用指针来保存地址
565     //fun3();        //8.2.1 空指针
566     //fun4();        //8.2.3 用指针来访问值
567     //fun5();        //8.2.4 指针地址,指针保存的地址和该地址的值
568     //fun6();        //8.2.5 指针对数值的操作
569     //fun7();        //8.2.6 更换指针保存的地址
570     //fun8();        //8.3.2 用指针创建堆中空间
571     //fun9();        //8.3.3 用指针删除堆中空间
572     //fun10();        //8.4.2 在堆中删除对象
573     //fun11();        //8.4.4 访问对中的数据成员
574     //fun12();        //8.4.5 在构造函数中开辟内存空间(不明白)
575     //fun13();        //8.4.6 对象在栈与堆中的不同(不明白)
576     //fun14();        //8.5 this指针                
577     //fun15();        //8.6 指针的常见错误
578     //fun16();        //8.7.1 指针的加减运算
579     //fun17();        //8.7.2 指针的赋值运算
580     //fun18();        //8.7.3 指针的相减运算
581     //fun19();        //8.7.4 指针的比较运算
582     //fun20();        //8.8.1 常量指针
583     //fun21();        //8.8.2 指向常量的指针
584     //fun22();        //8.8.3 指向常量的常指针
585 
586     return 0;
587 }