菜鸟资源网站全面焕新升级啦!全新的界面设计,简洁而不失雅致,让您一目了然,轻松上手。我们还对资源分类进行了细致梳理,确保各类资源条理清晰,便于您按需筛选与查找。 立即查看
通知图标

正在访问 第三章丨C++编程宝典:快速上手、深入进阶、挑战高级技巧,助你成为编程达人

第三章丨C++编程宝典:快速上手、深入进阶、挑战高级技巧,助你成为编程达人

第三章丨C++编程宝典:快速上手、深入进阶、挑战高级技巧,助你成为编程达人

接第二章C++编程宝典 2.5. 默认参数(default parameters) 通常情况下,函数在调用时,形参从实参那里取得值。对于多次调用用一函数同一实参时,C++给出了更简单的处理办法。给形参以默认值,这样就不用从实参那里取值了。 ...

当前版本

软件大小

软件语言

是否破解

接第二章C++编程宝典

2.5. 默认参数(default parameters)
通常情况下,函数在调用时,形参从实参那里取得值。对于多次调用用一函数同一实参时,C++给出了更简单的处理办法。给形参以默认值,这样就不用从实参那里取值了。
2.5.1. 示例
单个参数

  1. #include
  2. #include
  3. using namespace std;
  4. void weatherForcast(char * w="sunny")
  5. {
  6. time_t t = time(0);
  7. char tmp[64];
  8. strftime( tmp, sizeof(tmp), "%Y/%m/%d %X %A ",localtime(&t) );
  9. cout<<tmp<< "today is weahter "<<w<<endl;
  10. }
  11. int main()
  12. {
  13. //sunny windy cloudy foggy rainy
  14. weatherForcast();
  15. weatherForcast("rainny");
  16. weatherForcast();
  17. return 0;
  18. }

多个参数

  1. float volume(float length, float weight = 4,float high = 5)
  2. {
  3. return length*weight*high;
  4. }
  5. int main()
  6. {
  7. float v = volume(10);
  8. float v1 = volume(10,20);
  9. float v2 = volume(10,20,30);
  10. cout<<v<<endl;
  11. cout<<v1<<endl;
  12. cout<<v2<<endl;
  13. return 0;
  14. }

2.5.2. 规则
1,默认的顺序,是从右向左,不能跳跃。
2,定义在前,调用在后(此时定义和声明为一体),默认认参数在定义处。声明在前,调用在后,默认参数在声明处。
3,一个函数,不能既作重载,又作默认参数的函数。当你少写一个参数时,系统 无法确认是重载还是默认参数。

  1. void print(int a)
  2. {
  3. }
  4. void print(int a,int b =10)
  5. {
  6.  
  7. }
  8. int main()
  9. {
  10. print(10);
  11. return 0;
  12. }
  1. main.cpp:16: error: call of overloaded 'print(int)' is ambiguous
  1. print(10);

2.6. 引用(Reference)
2.6.1. 引用的概念
变量名,本身是一段内存的引用,即别名(alias)。此处引入的引用,是为己有变量起一个别名。
声明如下

  1. int main()
  2. {
  3. int a;
  4. int &b = a;
  5. }

2.6.2. 规则
1,引用没有定义,是一种关系型声明。声明它和原有某一变量(实体)的关系。故而类型与原类型保持一致,且不分配内存。与被引用的变量有相同的地址。
2,声明的时候必须初始化,一经声明,不可变更。
3,可对引用,再次引用。多次引用的结果,是某一变量具有多个别名。
4,&符号前有数据类型时,是引用。其它皆为取地址。

  1. int main()
  2. {
  3. int a,b;
  4. int &r = a;
  5. int &r = b; //错误,不可更改原有的引用关系
  6. float &rr = b; //错误,引用类型不匹配
  7. cout<<&a<<&r<<endl; //变量与引用具有相同的地址。
  8. int &ra = r; //可对引用更次引用,表示 a 变量有两个别名,分别是 r 和 ra
  9. }

2.6.3. 应用
C++很少使用独立变量的引用,如果使用某一个变量,就直接使用它的原名,没有必要使用他的别名。
作函数参数引用 (call by value)

  1. void swap(int a, int b); //无法实现两数据的交换
  2. void swap(int *p, int *q); //开辟了两个指针空间实现交换

作函数参数引用 (call by reference)

  1. void swap(int &a, int &b){
  2. int tmp;
  3. tmp = a;
  4. a = b;
  5. b = tmp;
  6. }
  7. int main(){
  8. int a = 3,b = 5;
  9. cout<<"a = "<<a<<"b = "<<b<<endl;
  10. swap(a,b);
  11. cout<<"a = "<<a<<"b = "<<b<<endl;
  12. return 0;
  13. }

c++中引入引用后,可以用引用解决的问题。避免用指针来解决
2.6.4. 引用提高
引用的本质是指针,C++对裸露的内存地址(指针)作了一次包装。又取得的指针的优良
特性。所以再对引用取地址,建立引用的指针没有意义。
1,可以定义指针的引用,但不能定义引用的引用。

  1. int a;
  2. int* p = &a;
  3. int*& rp = p; // ok
  4. int& r = a;
  5. int&& rr =

案例:

  1. #include
  2. using namespace std;
  3. void swap(char *pa,char *pb)
  4. {
  5. char *t;
  6. t = pa;
  7. pa = pb;
  8. pb = t;
  9. }
  10. void swap2(char **pa,char **pb)
  11. {
  12. char *t;
  13. t = *pa;
  14. *pa = *pb;
  15. *pb = t;
  16. }
  17. void swap3(char * &pa,char *&pb)
  18. {
  19. char *t;
  20. t = pa;
  21. pa = pb;
  22. pb = t;
  23. }
  24. int main()
  25. {
  26. char *pa = "china";
  27. char *pb = "america";
  28. cout<<"pa "<<pa<<endl;
  29. cout<<"pb "<<pb<<endl;
  30. // swap(pa,pb);
  31. // swap2(&pa,&pb);
  32. swap3(pa,pb);
  33. cout<<"pa "<<pa<<endl;
  34. cout<<"pb "<<pb<<endl;
  35. return 0;
  36. }

2,可以定义指针的指针(二级指针),但不能定义引用的指针。

  1. int a;
  2. int* p = &a;
  3. int** pp = &p; // ok
  4. int& r = a;
  5. int&* pr = &r; // error

3,可以定义指针数组,但不能定义引用数组,可以定义数组引用。

  1. int a, b, c;
  2. int* parr[] = {&a, &b, &c}; // ok
  3. int& rarr[] = {a, b, c}; // error
  4. int arr[] = {1, 2, 3};
  5. int (&rarr)[3] = arr; // ok 的

4,常引用
const 引用有较多使用。它可以防止对象的值被随意修改。因而具有一些特性。
(1)const 对象的引用必须是 const 的,将普通引用绑定到 const 对象是不合法的。这个原因比较简单。既然对象是 const 的,表示不能被修改,引用当然也不能修改,必须使用 const 引用。实际上,const int a=1; int &b=a;这种写法是不合法的,编译不过。
(2)const 引用可使用相关类型的对象(常量,非同类型的变量或表达式)初始化。
这个是 const 引用与普通引用最大的区别。const int &a=2;是合法的。double x=3.14; constint &b=a;也是合法的。
常引用原理:
const 引用的目的是,禁止通过修改引用值来改变被引用的对象。const 引用的初始化特性较为微妙,可通过如下代码说明

  1. double val = 3.14;
  2. const int &ref = val;
  3. double & ref2 = val;
  4. cout<<ref<<" "<<ref2<<endl;
  5. val = 4.14;
  6. cout<<ref<<" "<<ref2<

上述输出结果为 3 3.14 和 3 4.14。因为 ref 是 const 的,在初始化的过程中已经给定值,不允许修改。而被引用的对象是 val,是非 const 的,所以 val 的修改并未影响ref 的值,而 ref2 的值发生了相应的改变。
那么,为什么非 const 的引用不能使用相关类型初始化呢?实际上,const 引用使用相关类型对象初始化时发生了如下过程:

  1. int temp = val;
  2. const int &ref = temp;

如果 ref 不是 const 的,那么改变 ref 值,修改的是 temp,而不是 val。期望对 ref的赋值会修改 val 的程序员会发现 val 实际并未修改。

  1. int i=5;
  2. const int & ref = i+5;
  3. //此时产生了与表达式等值的无名的临时变量,
  4. //此时的引用是对无名的临时变量的引用。故不能更改。
  5. cout<<ref<<endl;

2.6.5. 引用的本质浅析
2.6.5.1. 大小与不可再引用
引用的本质是指针,是个什么样指针呢?可以通过两方面来探究,初始化方式和大小

  1. struct TypeP
  2. {
  3. char *p;
  4. };
  5. struct TypeC
  6. {
  7. char c;
  8. };
  9. struct TypeR
  10. {
  11. char& r; //把引用单列出来,不与具体的对像发生关系
  12. };
  13. int main()
  14. {
  15. // int a;
  16. // int &ra = &a;
  17. // const int rb; //const 类型必须要初始化。
  18. printf("%d %d %dn",sizeof(TypeP),sizeof(TypeC),sizeof(TypeR));
  19. return 0;
  20. }

结论:
引用的本质是,是对常指针 type * const p 的再次包装。char &rc == *pc double &rd == *p
2.6.5.2. 反汇编对比指针和引用
原程序

  1. #include
  2. using namespace std;
  3. void Swap(int *p, int *q)
  4. {
  5. int t = *p
  6. *p = *q;
  7. *q = t;
  8. }
  9. void Swap(int &p, int &q)
  10. {
  11. int t = p;
  12. p = q;
  13. q = t;
  14. }
  15. int main()
  16. {
  17. int a = 3; int b =5;
  18. Swap(a,b);
  19. Swap(&a,&b);
  20. return 0;
  21. }

汇编程序:

  1. [1] {
  2. 55 push %ebp
  3. <+0x0001> 89 e5 mov %esp,%ebp
  4. <+0x0003> 83 e4 f0 and $0xfffffff0,%esp
  5. <+0x0006> 83 ec 20 sub $0x20,%esp
  6. <+0x0009> e8 ce 0a 00 00 call 0x402130 <__main>
  7. [1] int a = 3; int b =5;
  8. <+0x000e> c7 44 24 1c 03 00 00 00 movl $0x3,0x1c(%esp)
  9. <+0x0016> c7 44 24 18 05 00 00 00 movl $0x5,0x18(%esp)
  10. [1] Swap(a,b);
  11. <+0x001e> 8d 44 24 18 lea 0x18(%esp),%eax
  12. <+0x0022> 89 44 24 04 mov %eax,0x4(%esp)
  13. <+0x0026> 8d 44 24 1c lea 0x1c(%esp),%eax
  14. <+0x002a> 89 04 24 mov %eax,(%esp)
  15. <+0x002d> e8 ac ff ff ff call 0x401632 <Swap(int&, int&)>
  16. [1] Swap(&a,&b);
  17. <+0x0032> 8d 44 24 18 lea 0x18(%esp),%eax
  18. <+0x0036> 89 44 24 04 mov %eax,0x4(%esp)
  19. <+0x003a> 8d 44 24 1c lea 0x1c(%esp),%eax
  20. <+0x003e> 89 04 24 mov %eax,(%esp)
  21. <+0x0041> e8 76 ff ff ff call 0x401610 <Swap(int*, int*)>
  22. [1] return 0;
  23. <+0x0046> b8 00 00 00 00 mov $0x0,%eax
  24. [1] }
  25. <+0x004b> c9 leave
  26. <+0x004c> c3 ret

0x401632 <Swap(int&,int&)>

  1. 12 [1]{
  2. 0x401632 55 push %ebp
  3. 0x401633 <+0x0001> 89 e5 mov %esp,%ebp
  4. 0x401635 <+0x0003> 83 ec 10 sub $0x10,%esp
  5. 13 [1] int t = p;
  6. 0x401638 <+0x0006> 8b 45 08 mov 0x8(%ebp),%eax
  7. 0x40163b <+0x0009> 8b 00 mov (%eax),%eax
  8. 0x40163d <+0x000b> 89 45 fc mov %eax,-0x4(%ebp)
  9. 14 [1] p = q;
  10. 0x401640 <+0x000e> 8b 45 0c mov 0xc(%ebp),%eax
  11. 0x401643 <+0x0011> 8b 10 mov (%eax),%edx
  12. 0x401645 <+0x0013> 8b 45 08 mov 0x8(%ebp),%eax
  13. 0x401648 <+0x0016> 89 10 mov %edx,(%eax)
  14. 15 [1] q = t;
  15. 0x40164a <+0x0018> 8b 45 0c mov 0xc(%ebp),%eax
  16. 0x40164d <+0x001b> 8b 55 fc mov -0x4(%ebp),%edx
  17. 0x401650 <+0x001e> 89 10 mov %edx,(%eax)
  18. 16 [1] }
  19. 0x401652 <+0x0020> c9 leave
  20. 0x401653 <+0x0021> c3 ret

0x401610 <Swap(int*,int*)>

  1. 6 [1] {
  2. 0x401610 55 push %ebp
  3. 0x401611 <+0x0001> 89 e5 mov %esp,%ebp
  4. 0x401613 <+0x0003> 83 ec 10 sub $0x10,%esp
  5. 7 [1] int t = *p;
  6. 0x401616 <+0x0006> 8b 45 08 mov 0x8(%ebp),%eax
  7. 0x401619 <+0x0009> 8b 00 mov (%eax),%eax
  8. 0x40161b <+0x000b> 89 45 fc mov %eax,-0x4(%ebp)
  9. 8 [1] *p = *q;
  10. 0x40161e <+0x000e> 8b 45 0c mov 0xc(%ebp),%eax
  11. 0x401621 <+0x0011> 8b 10 mov (%eax),%edx
  12. 0x401623 <+0x0013> 8b 45 08 mov 0x8(%ebp),%eax
  13. 0x401626 <+0x0016> 89 10 mov %edx,(%eax)
  14. 9 [1] *q = t;
  15. 0x401628 <+0x0018> 8b 45 0c mov 0xc(%ebp),%eax
  16. 0x40162b <+0x001b> 8b 55 fc mov -0x4(%ebp),%edx
  17. 0x40162e <+0x001e> 89 10 mov %edx,(%eax)
  18. 10 [1] }
  19. 0x401630 <+0x0020> c9 leave
  20. 0x401631 <+0x0021> c3 ret

对比结果
第三章丨C++编程宝典:快速上手、深入进阶、挑战高级技巧,助你成为编程达人
2.7. new/delete
c 语言中提供了 malloc 和 free 两个系统函数,完成对堆内存的申请和释放。而 c++则提供了两关键字 new 和 delete ;
2.7.1. new用法:
1.开辟单变量地址空间

  1. int *p = new int; //开辟大小为 sizeof(int)空间
  2. int *a = new int(5); //开辟大小为 sizeof(int)空间,并初始化为

2.开辟数组空间

  1. 一维: int *a = new int[100];开辟一个大小为 100 的整型数组空间
  2. 二维: int (*a)[6] = new int[5][6]
  3. 三维: int (*a)[5][6] = new int[3][5][6]
  4. 四维维及其以上:依此类推

2.7.2. delete用法:
1. int *a = new int;

  1. delete a; //释放单个 int 的空间

2.int *a = new int[5]

  1. delete []a; //释放 int

2.7.3. 综合用法

  1. #include
  2. #include
  3. #include
  4. #include
  5. using namespace std;
  6. int main()
  7. {
  8. int *p = new int(5);
  9. cout<<*p<<endl;
  10. delete p;
  11. char *pp = new char[10];
  12. strcpy(pp,"china");
  13. cout<<pp<<endl;
  14. delete []pp;
  15. string *ps = new string("china");
  16. cout<<*ps<<endl; //cout<<ps<<endl;
  17. delete ps;
  18. char **pa= new char*[5];
  19. memset(pa,0,sizeof(char*[5]));
  20. pa[0] = "china";
  21. pa[1] = "america";
  22. char **pt = pa;
  23. while(*pt)
  24. {
  25. cout<<*pt++<<endl;
  26. }
  27. delete []pt;
  28. int (*q)[3] = new int[2][3];
  29. for(int i=0; i<2; i++)
  30. {
  31. for(int j=0; j<3; j++)
  32. {
  33. q[i][j] = i+j;
  34. }
  35. }
  36. for(int i=0; i<2; i++)
  37. {
  38. for(int j=0; j<3; j++)
  39. {
  40. cout<<q[i][j];
  41. }
  42. cout<<endl;
  43. }
  44. delete []q;
  45. int (*qq)[3][4] = new int [2][3][4];
  46. delete []qq;
  47. }

2.7.4. 关于返回值

  1. int main()
  2. {
  3. //c 语言版本
  4. char *ps = (char*)malloc(100);
  5. if(ps == NULL)
  6. return -1;
  7. //C++ 内存申请失败会抛出异常
  8. try{
  9. int *p = new int[10];
  10. }catch(const std::bad_alloc e) {
  11. return -1;
  12. }
  13. //C++ 内存申请失败不抛出异常版本
  14. int *q = new (std::nothrow)int[10];
  15. if(q == NULL)
  16. return -1;
  17. return 0;
  18. }

2.7.5. 注意事项
1,new/delete 是关键字,效率高于 malloc 和 free.
2,配对使用,避免内存泄漏和多重释放。
2,避免,交叉使用。比如 malloc 申请的空间去 delete,new 出的空间被 free;
2.7.6. 更进一步
如果只是上两步的功能,c 中的 malloc 和 free 完全可以胜任,C++就没有必要更进一
步,引入这两个关键字。
此两关键字,重点用在类对像的申请与释放。申请的时候会调用构造器完成初始化,
释放的时候,会调用析构器完成内存的清理。以后我们会重点讲

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

常见问题

  • 如何安装和激活?

    每款软件会附带有安装教程,您打开安装包一目了然

  • 程序是否已损坏?文件损坏?还是其他错误?

    有错误问题,请您参考:https://www.xxx.com/error

  • 如何更新?正式激活后会发生什么情况?

    除非安装说明中另有说明,否则官方更新可能会导致无法激活。 要从本网站更新软件,您需要在此处下载此软件的新版本(如果可用),并将其安装在计算机上安装的版本之上(替换)。在这种情况下,您将保存此软件的激活和设置。

  • 如何下载?链接不起作用?

    我们使用百度网盘,132云盘和微软网盘,除了百度网盘,其他两款不限速,如果链接失效,请您联系客服处理

  • 已发布更新。我什么时候升级我的版本?

    所有软件如有更新,我们第一时间推送,视自己情况更新使用

  • 如何更改语言?

    打开“系统偏好设置”->“通用>语言和地区”->应用程序-“+”。 选择应用和语言。此方法适用于大多数应用程序。 Adobe 产品中的语言通常是在产品本身的安装阶段选择的。 游戏中的语言通常会在游戏本身的设置中发生变化。

  • 如何删除软件?

    有很多选择。最简单的方法是使用特殊的实用程序来卸载应用程序,例如App Cleaner Uninstaller 要删除 Adobe 产品,请使用 Creative Cloud Cleaner Tool

  • 需要远程帮助吗?

    网站已开通永久会员的可享受免费远程,如果非永久会员,远程安装另外收费

技术教程

第二章丨C++编程宝典:快速上手、深入进阶、挑战高级技巧,助你成为编程达人

2024-1-27 21:06:00

技术教程

第四章丨C++编程宝典:快速上手、深入进阶、挑战高级技巧,助你成为编程达人

2024-1-28 19:02:00

0 条回复 A文章作者 M管理员
欢迎您,新朋友,感谢参与互动!
    暂无讨论,说说你的看法吧
后退
榜单