背景:老师留了一个作业,对两个数组进行相加,但是总是会出现错误;首先我们需要知道当数组作为参数传递的时候是不能用 sizeof 的,因为当数组传入子函数就变成了普通的数组头;这时候使用 sizeof 只会检测到指针的长度;

我们用模板来传递数组,实际上并非模板可以传递数组,而是引用传递完成了这件事

对应的现象是:值传递的数组会衰减成指针

下面给出利用引用传递的代码(没有使用模板)

 1 #include<iostream>
2 using namespace std;
3
4 int P(int (&a)[5]);   //子函数
5 int main(){
6
7 int a[5]={0};
8
9 int b=P(a);
10
11 cout<<b<<endl;
12
13 return 0;
14 }
15 int P(int (&a)[5]){      //进行了引用传递
16
17 return sizeof(a)/sizeof(a[0]);
18 }

  在这个代码中我们发现一件事,如果要传递这个数组,我们首先要知道数组的位数,但是我们要求的不就是数组的位数吗,这就是上文我们做的,其实也是模板的主要作用:实参演绎,我们规定了两个参数,这两个参数到底谁是5位数组,谁是10位数组,这个工作在模板中被自动的完成了,综合了上述两种技术我们实现了数组的传递

  其次,我们需要知道子函数返回的数组的时候也很麻烦,不仅仅因为返回的是指针,更是因为在子函数中定义的数组会随着函数的结束而释放,最终只留下数组头一个数据可以使用,所以我们用动态内存,去主动的分配一个空间给数组


现在我们把操作和方法放在下面:

模板: 传入一个数组(实现泛型编程,因为要传入的这个数组长度是不确定的)
引用传递: 这里没有操作原来的数,仅仅是为了减少拷贝的操作
new: 给数组创建内存
delete: 配合new,释放内存

  

  

以下代码思路:

先弄两个数组,一起传入到子函数中

由子函数创建新的数组,通过加减法给新的数组赋值,(new)

操作完新的数组之后结束程序(delete)

 1 #include<iostream>
2
3 using namespace std;
4
5 template <typename T1,typename T2> //要在模板参数列表中定义两个模板参数;因为:
6 int* plusArr(T1& a,T2& b); //将来传入的int[10]和int[5]是两个不同的类型
7
8 int main(){
9
10 int a[10]={1,2,3,4,5,6,7,8,9,0};
11 int b[5]={3,4,5,6,7};
12
13 int* sum=plusArr(a,b); //用sum保存这个指针,因为plusArr栈会清掉(包括指针p)
14
15 int i=0;
16 while(sum[i]!='\0'){
17 cout<<sum[i]<<' ';
18 ++i;
19 }
20
21 delete[] sum; //释放内存 在此,delete一定要加中括号[]!!
22 }
23
24 template<typename T1,typename T2>
25 int* plusArr(T1& a,T2& b){
26
27 int m=(int)sizeof(a)/sizeof(a[0]);
28 int n=(int)sizeof(b)/sizeof(b[0]);
29
30 if(m>n){
31 int* p=new int[m+1]; //在堆上分配了动态内存 (并未初始化)
32 for(int i=0;i<n;i++){ //开始赋值
33 p[i]=a[i]+b[i];
34 }
35 for(int i=n;i<m;i++){
36 p[i]=a[i];
37 }
38 p[m]='\0'; //用来标志
39 return p;
40 }
41 else{ //上面的是a长度大,下面b同理
42 int* p=new int[n+1];
43 for(int i=0;i<m;i++){
44 p[i]=a[i]+b[i];
45 }
46 for(int i=n;i<m;i++){
47 p[i]=b[i];
48 }
49 p[n]='\0';
50 return p;
51 }
52
53 }

  这个函数写出来呢,主要是验证一些函数的用法,这些函数虽然在这个程序中显得“过分”了,但是在将来涉及到复用的时候,像这种泛型编程就可以大显身手,顺便复习一下new delete


更加深入的理解:

在人民邮电出版社《C++模板:tamplate》一书中开头就提醒我们模板的定义一定要写常量引用,而且注意const的顺序一定是在后面;

下面我们列出一个模板的定义,并尝试去理解他的形式参数性质:

 1 #include<iostream>
2 int main(){
3 int* b;
4 int* &a=b; //这里对指针a的操作等于直接对指针b进行操作
5
6 int const c;
7 int* const d; //定义一个正常的常量指针d
8
9 int* n;
10 int* const &m=n; //定义一个常量指针的引用,这里n是常量,所有对m的操作最终会作用到n上
11
12 //在模板中我们经常看到如下定义
13 tamplate<typename T>
14 T const& name(T const& a,T const& b){ //这里是引用传递,并且我们不会用引用去更改外面的值
15 ;
16 }
17
18 return 0;
19 }

转载请注明来源

面向对象程序设计(二):C++模板初探的更多相关文章

  1. python基础16 ----面向对象程序设计二

    一.继承与派生 1.继承的定义:继承是一种创建新类的方式,即在类中提取共同的部分创建出一个类,这样的类称为父类,也可称为基类和超类,新建的类称为派生类或子类. 2.单继承:就相当于子类继承了一个父类. ...

  2. 2017-2018-2 20165206 实验二《Java面向对象程序设计》实验报告

    2017-2018-2 20165206 实验二<Java面向对象程序设计>实验报告 一.实验报告封面 课程:Java程序设计 班级:1652班 姓名:韩啸 学号:20165206 指导教 ...

  3. 20165323 实验二 Java面向对象程序设计

    一.实验报告封面 课程:Java程序设计 班级:1653班 姓名:杨金川 学号:20165323 指导教师:娄嘉鹏 实验日期:2018年4月16日 实验时间:13:45 - 15:25 实验序号:二 ...

  4. 20155228 实验二 Java面向对象程序设计

    20155228 实验二 Java面向对象程序设计 实验内容 1. 初步掌握单元测试和TDD 2. 理解并掌握面向对象三要素:封装.继承.多态 3. 初步掌握UML建模 4. 熟悉S.O.L.I.D原 ...

  5. 20155225 实验二《Java面向对象程序设计》实验报告

    20155225 实验二<Java面向对象程序设计>实验报告 一.单元测试 三种代码 知道了伪代码.产品代码.测试代码的关系和用途,并根据老师的例子,按测试代码调试了产品代码. 值得注意的 ...

  6. 20155232 实验二《Java面向对象程序设计》实验报告

    20155232 实验一<Java面向对象程序设计>实验报告 实验内容 1.初步掌握单元测试和TDD 2.理解并掌握面向对象三要素:封装.继承.多态 3.初步掌握UML建模 4.熟悉S.O ...

  7. 20165202 实验二 Java面向对象程序设计

    实验二 Java面向对象程序设计 一.实验报告封面 课程:Java程序设计 班级:1652班 姓名:贾海粟 学号:20165202 指导教师:娄嘉鹏 实验日期:2018年4月16日 实验时间:15:3 ...

  8. [.net 面向对象程序设计进阶] (23) 团队开发利器(二)优秀的版本控制工具SVN(上)

    [.net 面向对象程序设计进阶] (23) 团队开发利器(二)优秀的版本控制工具SVN(上) 本篇导读: 上篇介绍了常用的代码管理工具VSS,看了一下评论,很多同学深恶痛绝,有的甚至因为公司使用VS ...

  9. [.net 面向对象程序设计进阶] (17) 多线程(Multithreading)(二) 利用多线程提高程序性能(中)

    [.net 面向对象程序设计进阶] (17) 多线程(Multithreading)(二) 利用多线程提高程序性能(中) 本节要点: 上节介绍了多线程的基本使用方法和基本应用示例,本节深入介绍.NET ...

  10. [.net 面向对象程序设计进阶] (15) 缓存(Cache)(二) 利用缓存提升程序性能

    [.net 面向对象程序设计进阶] (15) 缓存(Cache)(二) 利用缓存提升程序性能 本节导读: 上节说了缓存是以空间来换取时间的技术,介绍了客户端缓存和两种常用服务器缓布,本节主要介绍一种. ...

随机推荐

  1. 优秀的Kafka GUI客户端、可视化管理工具、监控工具

    想要查看Topic里的消息却找不到软件,想要查看或更新Broker.Topic配置,想要监控Broker服务器状态?试试下面的Kafka GUI工具--Kafka Assistant 官网地址:htt ...

  2. 匿名方法、Lambda表达和自定义泛型委托以及Func、Action系统泛型委托

    1.匿名方法的概念:一个方法没有具体的名称,而只有关键字delegate.方法参数.方法体.这种方法是匿名方法. 匿名方法的好处:将具体方法和委托直接关联在一起,如果我们基于委托只需要一个方法的时候, ...

  3. 【云原生 · Kubernetes】部署kube-apiserver集群

    个人名片: 因为云计算成为了监控工程师‍ 个人博客:念舒_C.ying CSDN主页️:念舒_C.ying 部署kube-apiserver集群 10.1 创建kube-apiserver 证书 10 ...

  4. 【Java并发008】原理层面:ReentrantLock中 await()、signal()/signalAll()全解析

    一.前言 上篇的文章中我们介绍了AQS源码中lock方法和unlock方法,这两个方法主要是用来解决并发中互斥的问题,这篇文章我们主要介绍AQS中用来解决线程同步问题的await方法.signal方法 ...

  5. HDLBits答案——Verification: Reading Simulations

    1 Finding bugs in code 1.1 Bugs mux2 module top_module ( input sel, input [7:0] a, input [7:0] b, ou ...

  6. phpword 模板文件导出word到服务器 并浏览器下载

    模板文件填充 然后生成新文件 //调用PHPwordrequire_once(ROOTPATH . "inc/vendor/autoload.php"); $phpWord = n ...

  7. 【SQL查询】必会的常用函数:条件函数、日期函数、文本函数、窗口函数

    〇.概述 1.内容 选择(双分支.多分支) 一.条件函数 1.计算25岁以上和以下的用户数量 CASE THEN END多分支选择 SELECT (CASE WHEN age>=25 THEN ...

  8. 【大数据面试】Flink 01 概述:包含内容、层次架构、运行组件、部署模式、任务提交流程、任务调度概念、编程模型组成

    一.概述 1.介绍 对无界和有界数据流进行有状态计算的分布式引擎和框架,并可以使用高层API编写分布式任务,主要包括: DataSet API(批处理):静态数据抽象为分布式数据集,方便使用操作符进行 ...

  9. PyQt4编写界面的两种方式

    PyQt4编写界面的两种方式 应用PyQt4开发图形化界面有两种方式,一种是直接通过QtDesigner通过提供的窗口部件拖拽进行GUI创建,另外一种是直接进行编程实现. 第一种,QtDesigner ...

  10. MySQL函数--时间格式--流程控制if判断

    目录 一:函数 1.MySQL什么是函数? 2.通过help查看函数帮助 3.移除指定字符 4.大小写转换 5.获取左右起始指定个数字符 6.返回读音相似值(对英文效果) 二:时间格式实战案例 1.时 ...