首页 > 代码库 > 范磊 C++ 第8章 指针

范磊 C++ 第8章 指针

  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就是改变了*p106 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 A205 {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 A1237 {238 private:239     int i;240 public:241     int get() const242     {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 A2263 {264 private:265     int* i;266 public:267     A2();268     ~A2();269     int get() const270     {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 A3302 {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 A4341 {342 private:343     int i;344 public:345     int get() const346     {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     else464     {465         cout << "p1大于p的内存地址. \n" ;466     }467 468 }469 470 471 //-------------------------------------------------472 //8.8.1 常量指针473 //常量指针:指针的值不能改变. 这个指针是一个常量,是一个不变量.474 class A5475 {476 private:477     int i;478 public:479     int get() const480     {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 extern497     //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 A6509 {510 private:511     int i;512 public:513     int get() const514     {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 A7535 {536 private:537     int i;538 public:539     int get() const540     {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 extern551     //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 }

 

范磊 C++ 第8章 指针