C++ primer 习题笔记第10~12章

来源:互联网 发布:java web编程宝典 pdf 编辑:程序博客网 时间:2024/06/17 21:38
1、 假定 v 是 vector<double> 类型的对象,则调用accumulate(  v.begin(),  v.end(),  0  )是否有错?如果有的话,错在哪里?

【解答】

没有错,accumulate 函数必须满足第三个实参的类型与容器内的意思匹配,或者可以转化为第三个实参的类型。本题中 double 可以转化为 int 类型,但是会有较大误差。


2、算法不改变它所操纵的容器的大小,为什么使用 back_inserter 也不能突破这个限制?

【解答】
在使用 back_inserter 是,不是算法直接改变它所操作的容器的大小,而是算法操作迭代器 back_inserter, 迭代器的行为导致了容器的大小改变。


3、你认为为什么算法不改变容器的大小?

【解答】
为了使得算法能够独立于容器,从而普适性更好,真正成为“泛型”算法。


4、为什么必须使用 erase,  而不是定义一个泛型算法来删除容器中的元素。

【解答】
泛型算法的原则就是不改变容器的大小。


5、使用一对 istream_iterator 对象初始化一个 int 型的 vector 对象。

【解答】

istream_iterator<int> cin_it(  cin ), end;
vector<int >  iVec( cin_it, end  );


6、列出五种迭代器类型及其各自支持的操作。

【解答】
输入迭代器:  ==   !=   ++  *   ->
输出迭代器: ++ *
前向迭代器:  == !=  ++ *  ->
双向迭代器:  == != ++ *   ->   -- 
随机访问迭代器:       ==    !=   ++   *   ->   <  <=   >    >=  + -  +=  -=


7、list拥有双向迭代器,vector拥有随机访问迭代器。 


8、解释下列代码错误的原因,指出哪些错误可以在编译时捕获。
(a) string sa[10];
const vector<string> file_names( sa, sa+6 );
(b) const vector<int> ivec;
fill ( ivec.begin(), ivec.end(), ival );
(c) sort( ivec.begin(), ivec.rend() );
(d) sort( ivec1.begin(), ivec2.end() );

【解答】
(a) const  类型的 vector<string>对象,不可以写入,错误。 
(b)  错了,两个实参迭代器是 cosnt 迭代器,不能用来修改容器中的元素
(c)  错了,用于算法的实参的两个迭代器必须是相同类型。
(d)  错了,用于算法参数的迭代器必须属于同一个迭代器。 
       前三个错误均可以在编译时捕获。

(d)  不能在编译时捕获。 


9、假设 lst 是存储了 100 个元素的容器,请解释下面的程序段,并修正你认为的错误。
vector<int> vec1;
reverse_copy ( lst.begin(), lst.end(), vec1.begin() );

【解答】
这段程序试图将 lst 中的元素以逆序的方式复制到vec1 容器中。
可能的错误为:
1) vec1 是一个空容器,尚未分配存储空间,可改为: vector<int> vec1(100);
2)另外 lst 容器中存储的元素不一定为 int 型。应该保证两种容器内存储的值的类型相同或者可以进行转换。


10、解释类声明与类定义之间的差异。何时使用类声明?何时使用类定义?

【解答】
类声明是不完全类型,只能以有限方式使用,不能定义该类型的对象,只能用于定义指向该类型的指针及引用,或者声明使用该类型作为形参类型或返回类型的函数。类定义,一旦类被定义,我们就可以知道所有类的成员,以及存储该类的对象所需的存储空间。在创建类的对象之前或者使用引用或指针访问类的成员之前必须定义类。


11、通过 this 指针引用成员虽然合法,但却是多余的。讨论显示地使用 this 指针访问成员的优缺点。

【解答】
优点:当需要将一个对象作为整体引用而不是引用对象的一个成员时,使用 this,则该函数返回对调用该函数的对象的引用。
可以非常明确地指出访问的是调用该函数的对象的成员,且可以在成员函数中使用与数据成员同名的形参。
缺点:不必要使用,代码多余。


12、列出在类作用域中的程序文本部分。

【解答】
类的定义体;在类外定义的成员函数:形参表、成员函数体,但不包含函数的返回类型。


13、 解释下述代码,指出每次使用 Type 或 initVal时用到的是哪个名字定义。如果存在错误,说明如何改正。
Typedef string type;
Type initVal();
class Exercise {
public:
// ...
typedef double Type;
Type setVal(Type); 

Type initVal();
private:
int val;
};
Type Exercise::setVal(Type parm)   {
val = parm + initVal();
}
成员函数 setVal  的定义有错。进行必要的修改以便类 Exercise 使用全局的类型别名 Type 和全局函数initVal.
【解答】

在类的定义体内,两个成员函数的返回类型和setVal 的形参使用的 Type 都是类内部定义的类型别名 Type;在类外的成员函数 setVal 的定义体内,形参的类型 Type 是 Exercise 类内定义的类型别名 Type,返回类型的 Type 使用的是全局的类型别名 Type。在 setVal 的定义体内使用的 initVal 函数,使用的是 Exercise 类的成员函数。在 SetVal 的函数定义有错: 1.缺少返回类型; 2.  此函数的返回类型是 string 类型的,而类中声明的函数返回类型是 double 类型的,不合法的函数重载,可以改为:
Exercise::Type Exercise::setVal(Type parm)  {
              val = parm + initVal();
              retur n val;
}


14、编译如下代码:
f(const vector<int>&);
int main()   {
     vector<int> v2;
     f(v2);   // shoule be ok
     f(42);   // shoule be an er ror
     retur n 0;
}
基于对 f 的第二个调用中出现的错误,我们可以对 vector 构造函数做出什么推断?如果该调用成功了,那么你能得出什么结论?

【解答】
可以做出以下推断:vector 中没有定义接受一个 int型参数的构造函数,或者即使定义了接受一个 int型参数的构造函数,该函数也被声明为了 explicit。如果调用成功了,则说明 vector 中定义了可以接受一个 int 型参数的构造函数。


15、pair 的数据成员为 Public,然而下面这段代码却不能编译,为什么?
pair< int,  int > p2 = (0, 42); // doesn‘t compile, 
why?
可能是因为 pair 类定义了构造函数,此时只能使用构造函数初始化成员,可改为:

pair<int,int>  p2( 0, 42 );


16、下面的 static 数据成员声明和定义哪些是错误的(如果有的话)?解释为什么。
// example.h
class Example   {
public:
    static double rate = 6.5;  错误
    static const int vecSize = 20;
    static vector<double> vec(vecSize);  错误
};
// example C
#include  ―example.h‖
double Example::rate;  错误
vector<double> Example::vec;  错误

【解答】
因为非 const static 成员的初始化必须放在类定义体的外部
下边对 static 成员 rate 和 vec 的定义也是错误的,因为此处必须给出初始值。
更正为:
class Example   {
public:
   static double rate; 
   static const int vecSize = 20;
   static vector<double> vec; 
};
// example C
#include  ―example.h‖
double Example::rate=  6.5;  
vector<double> Example::vec(vecSize);


0 0
原创粉丝点击