C++Primer(第五版 )第十六章 模版与泛型编程 章节编程练习答案

16.1 给出实例化的定义。

答:

当编译器实例化一个模版时,它使用实际的模版参数代替对应的模版参数来创建出模版的一个新“实例”。

16.2  编写并测试你自己版本的 compare 函数。

答:

16.4  编写行为类似标准库 find 算法的模版。函数需要两个模版类型参数,一个表示函数的迭代器参数,另一个表示值的类型。使用你的函数在一个 vector<int> 和一个list<string>中查找给定值。

答:

16.5  为6.2.4节中的print函数编写模版版本,它接受一个数组的引用,能处理任意大小、任意元素类型的数组。

答:

16.6 你认为接受一个数组实参的标准库函数 begin 和 end 是如何工作的?定义你自己版本的 begin 和 end

答:

16.7  编写一个 constexpr 模版,返回给定数组的大小。

答:

16.8  在第97页的“关键概念”中,我们注意到,C++程序员喜欢使用 != 而不喜欢 < 。解释这个习惯的原因。

答:

因为大多数类只定义了 != 操作而没有定义 < 操作,使用 != 可以降低对要处理的类型的要求。

16.9  什么是函数模版,什么是类模版?

答:

一个函数模版就是一个公式,可用来生成针对特定类型的函数版本。类模版是用来生成类的蓝图的,与函数模版的不同之处是,编译器不能为类模版推断模版参数类型。如果我们已经多次看到,为了使用类模版,我们必须在模版名后的尖括号中提供额外信息。

16.10  当一个类模版被实例化时,会发生什么?

答:

一个类模版的每个实例都形成一个独立的类。

16.11 下面 List 的定义是错误的。应如何修改它?

答:

16.12  编写你自己版本的 Blob 和 BlobPtr 模版,包含书中未定义的多个const成员。

答:

16.14  编写 Screen 类模版,用非类型参数定义 Screen 的高和宽。

答:

16.16  将 StrVec 类重写为模版,命名为 Vec

答:

16.17  声明为 typename 的类型参数和声明为 class 的类型参数有什么不同(如果有的话)?什么时候必须使用typename

答:

没有什么不同。仅当我们希望通知编译器一个名字表示类型时,必须使用关键字 typename,而不能使用 class

16.18  解释下面每个函数模版声明并指出它们是否非法。更正你发现的每个错误。

答:

  • (a) 非法。应该为 template <typename T, typename U, typename V> void f1(T, U, V);
  • (b) 非法。应该为 template <typename T> T f2(int &t);
  • (c) 非法。应该为 template <typename T> inline T foo(T, unsigned int*);
  • (d) 非法。应该为 template <typename T> T f4(T, T);
  • (e) 非法。Ctype 被隐藏了。

16.19  编写函数,接受一个容器的引用,打印容器中的元素。使用容器的 size_type 和 size成员来控制打印元素的循环。

答:

16.20  重写上一题的函数,使用begin 和 end 返回的迭代器来控制循环。

答:

16.21  编写你自己的 DebugDelete 版本。

答:

16.25  解释下面这些声明的含义。

答:

前者是模版声明,后者是实例化定义。

16.33  指出在模版实参推断过程中允许对函数实参进行的两种类型转换。

答:

  • const 转换:可以将一个非 const 对象的引用(或指针)传递给一个 const 的引用(或指针)形参。
  • 数组或函数指针转换:如果函数形参不是引用类型,则可以对数组或函数类型的实参应用正常的指针转换。一个数组实参可以转换为一个指向其首元素的指针。类似的,一个函数实参可以转换为一个该函数类型的指针。

16.34  对下面的代码解释每个调用是否合法。如果合法,T 的类型是什么?如果不合法,为什么?

答:

  • (a) 不合法。compare(const char [3], const char [6]), 两个实参类型不一致
  • (b) 合法。compare(const char [4], const char [4]).

16.35  下面调用中哪些是错误的(如果有的话)?如果调用合法,T 的类型是什么?如果调用不合法,问题何在?

答:

  • (a) 合法,类型为char
  • (b) 合法,类型为double
  • (c) 合法,类型为char
  • (d) 不合法,这里无法确定T的类型是float还是double

16.36  进行下面的调用会发生什么:

答:

(a) f1(int*, int*);
(b) f2(int*, int*);
(c) f1(const int*, const int*);
(d) f2(const int*, const int*);
(e) f1(int*, const int*); 这个使用就不合法
(f) f2(int*, const int*);

16.38  当我们调用 make_shared 时,必须提供一个显示模版实参。解释为什么需要显式模版实参以及它是如果使用的。

答:

如果不显示提供模版实参,那么 make_shared 无法推断要分配多大内存空间。

16.40  下面的函数是否合法?如果不合法,为什么?如果合法,对可以传递的实参类型有什么限制(如果有的话)?返回类型是什么?

答:

合法。该类型需要支持 + 操作。

16.41  编写一个新的 sum 版本,它返回类型保证足够大,足以容纳加法结果。

答:

16.42  对下面每个调用,确定 T 和 val 的类型:

答:

(a) int&
(b) const int&
(c) int&&

16.48  编写你自己版本的 debug_rep 函数。

答:

16.49  解释下面每个调用会发生什么:

答:

    g(42);    	//g(T )
    g(p);     	//g(T*)
    g(ci);      //g(T)   
    g(p2);      //g(T*)  
  
    f(42);    	//f(T)
    f(p);     	//f(T)
    f(ci);    	//f(T)
    f(p2);      //f(const T*)

16.51  调用本节中的每个 foo,确定 sizeof...(Args) 和 sizeof...(rest)分别返回什么。

答:

16.53  编写你自己版本的 print 函数,并打印一个、两个及五个实参来测试它,要打印的每个实参都应有不同的类型。

答:

16.61  定义你自己版本的 make_shared

答:

16.63  定义一个函数模版,统计一个给定值在一个vecor中出现的次数。测试你的函数,分别传递给它一个doublevector,一个intvector以及一个stringvector

答:

16.65  在16.3节中我们定义了两个重载的 debug_rep 版本,一个接受 const char* 参数,另一个接受 char * 参数。将这两个函数重写为特例化版本。

答:

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值