当前位置: 首页 > news >正文

C++的相关习题(2)

初阶模板

在这里插入图片描述

下面有关C++中为什么用模板类的原因,描述错误的是? ( )

A.可用来创建动态增长和减小的数据结构

B.它是类型无关的,因此具有很高的可复用性

C.它运行时检查数据类型,保证了类型安全

D.它是平台无关的,可移植性

A.模板可以具有非类型参数,用于指定大小,可以根据指定的大小创建动态结构

B.模板最重要的一点就是类型无关,提高了代码复用性

C.模板运行时不检查数据类型,也不保证类型安全,相当于类型的宏替换,故错误

D.只要支持模板语法,模板的代码就是可移植的

在下列对fun的调用中,错误的是( )

template < class T>

T fun(T x,T y){

return x *x+y *y;

}

A.fun(1, 2)

B.fun(1.0, 2)

C.fun(2.0, 1.0)

D.fun< float>(1, 2.0)

A.通过参数推导,T为int,不存在二义性,调用正确

B.由于参数类型不一样,模板不支持类型转换,推导参数会产生二义性,编译错误

C.通过参数推导,T为float,不存在二义性,调用正确

D.通过类型实例化函数,调用正确

下列关于模板的说法正确的是( )

A.模板的实参在任何时候都可以省略

B.类模板与模板类所指的是同一概念

C.类模板的参数必须是虚拟类型的

D.类模板中的成员函数全是模板函数

A. 模板实参省略意思为隐式实例化,一般情况下都使用隐式实例化,不需指定模板类型参数,让编译器进行推导

​ 但有些情况下编译器推导时可能会有歧义,比如:模板参数只有一个类型T,但是用两个不同类型隐式实例化

 template<class T>T Add(const T& x, const T& y){return x + y;}int main(){Add(10, 20);    // 正确Add(1.2, 30);   // 编译失败, 改正 Add<int>(1.2, 20) 或者 Add((int)1.2, 20)return 0;}

所以模板参数不是任何情况下都可以省略,要结合具体的使用场景,因此A的说法是错误的。

B.类模板是一个类家族,模板类是通过类模板实例化的具体类

C.C++中类模板的参数即为模板参数列表中内容,有两种方式:类型参数和非类型参数

​ 类型参数:即类型参数化,将来实例化为具体的实际类型,有点像函数的形参,形参可以接受不同值的实参

​ 非类型参数:在定义时给定了具体的类型,用该类型定义的为常量,比如:

template<class T, size_t N>class array{// ...};

D.正确,定义时都必须通过完整的模板语法进行定义。 因为所有类模板的成员函数,放在类外定义时,需要在函数名前加类名,而类名实际为ClassName< T>,所以定义时还需加模板参数列表

template<class T>size_t Stack<T>::size(){return _size;}

因此类模板中的成员函数都是函数模板

下列的模板声明中,其中几个是正确的( )

1)template

2)template<T1,T2>

3)template<class T1,T2>

4)template<class T1,class T2>

5)template<typename T1,T2>

6)template<typename T1,typename T2>

7)template<class T1,typename T2>

8)<typename T1,class T2>

A.2

B.3

C.4

D.5

A.1.模板语法错误,2.没有关键字class或typename指定类型,3.T2缺少class或typename

B.正确, 4,6,7为正确声明

C.5.T2缺少class或typename

D.8.缺少template

下列描述错误的是( )

A.编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础

B.函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具

C.模板分为函数模板和类模板

D. 模板类跟普通类以一样的,编译器对它的处理时一样的

A.模板是代码复用的重要手段

B.函数模板不是一个具体函数,而是一个函数家族

C.目前涉及到的模板就两类,函数模板与类模板

D.模板类是一个家族,编译器的处理会分别进行两次编译,其处理过程跟普通类不一样

​ }

​ return 0;

}

A.程序运行崩溃

B.1 2 3 4 5 0 6 7 8 9

C.1 2 3 4 5 6 7 8 9

D.1 2 3 4 6 7 8 9

分析:当迭代器的值为0时,此时会进行删除,删除后如果迭代器不重新赋值,会导致原来的迭代器失效,此时针对一个已经失效的迭代器在进行++,会导致程序崩溃

故答案为A

2.下面关于迭代器失效的描述哪个是错误的( )

A.vector的插入操作一定会导致迭代器失效

B.vector的插入操作有可能不会导致迭代器失效

C.vector的删除操作只会导致指向被删除元素及后面的迭代器失效

D.vector的删除操作只会导致指向被删除元素的迭代器失效

A.vector的插入操作如果导致底层空间重新开辟,则迭代器就会失效。如果空间足够,不扩容时,迭代器不一定失效,比如push_back尾插,元素插入到空间末尾,在不扩容时不会对迭代器产生影响

B.参考A的解释。

C.vector删除,当前元素肯定失效,后面元素会牵扯到移动数据,因此删除元素后面的迭代器也会失效

D. vector的删除操作不光会导致指向被删除元素的迭代器失效,删除元素后面的迭代器也会失效

list的特性及使用

1.下面有关vector和list的区别,描述错误的是( )

A.vector拥有一段连续的内存空间,因此支持随机存取,如果需要高效的随机存取,应该使用vector

B.list拥有一段不连续的内存空间,如果需要大量的插入和删除,应该使用list

C.vector::iterator支持“+”、“+=”、“<”等操作符

D.list::iterator则不支持“+”、“+=”、“<”等操作符运算,但是支持了[ ]运算符

答案:D

A.如果想大量随机读取数据操作,vector是首选的容器

B.如果想大量的插入和删除数据,list效率较高,是首选

C.由于vector底层是连续空间,其迭代器就是相应类型的指针,所以支持对应的操作

D.list迭代器不支持[]运算符

2.以下代码实现了从表中删除重复项的功能,请选择其中空白行应填入的正确代码( )

template

void removeDuplicates(list &aList)

{

​ T curValue;

​ list::iterator cur, p;

​ cur = aList.begin();

​ while (cur != aList.end())

​ {

​ curValue = *cur;

​ //空白行 1

​ while (p != aList.end())

​ {

​ if (*p == curValue)

​ {

​ //空白行 2

​ }

​ else

​ {

​ p++;

​ }

​ }

​ }

}

A. p=cur+1;aList.erase(p++);

B.p=++cur; p == cur ? cur = p = aList.erase§ : p = aList.erase§;

C.p=cur+1;aList.erase§;

D.p=++cur;aList.erase§;

答案:B

分析:迭代p需要迭代不重复节点的下一节点,重要的是cur迭代器需要往下迭代,因此cur需要往前移动,二答案A C的cur都不会改变,空白行2是当需要找到重复值时进行节点删除,当删除时当前迭代器会失效,因此需要将迭代器p往后迭代,所以答案为 B

3.以下程序输出结果为( )

int main()

{

​ int ar[] = { 0,1, 2, 3, 4, 5, 6, 7, 8, 9 };

​ int n = sizeof(ar) / sizeof(int);

​ list mylist(ar, ar+n);

​ list::iterator pos = find(mylist.begin(), mylist.end(), 5);

​ reverse(mylist.begin(), pos);

​ reverse(pos, mylist.end());

​ list::const_reverse_iterator crit = mylist.crbegin();

​ while(crit != mylist.crend())

​ {

​ cout<<*crit<<" ";

​ ++crit;

​ }

​ cout<<endl;

}

A.4 3 2 1 0 5 6 7 8 9

B.0 1 2 3 4 9 8 7 6 5

C.5 6 7 8 9 0 1 2 3 4

D.5 6 7 8 9 4 3 2 1 0

答案:C

分析:list::iterator pos = find(mylist.begin(), mylist.end(), 5); //找到5的位置

​ reverse(mylist.begin(), pos);//逆置0 1 2 3 4 为 4 3 2 1 0

​ reverse(pos, mylist.end()); //逆置5 6 7 8 9 为 9 8 7 6 5

​ 逆置完成之后其数据为:4 3 2 1 0 9 8 7 6 5

​ list::const_reverse_iterator crit = mylist.crbegin(); //反向迭代器进行反向访问

​ while(crit != mylist.crend()){}

​ 所以答案为:5 6 7 8 9 0 1 2 3 4

​ C答案

下面程序的输出结果正确的是( )

int main()

{

​ int array[] = { 1, 2, 3, 4, 0, 5, 6, 7, 8, 9 };

​ int n = sizeof(array) / sizeof(int);

​ list mylist(array, array+n);

​ auto it = mylist.begin();

​ while (it != mylist.end())

​ {

​ if(* it != 0)

​ cout<<* it<<" ";

​ else

​ it = mylist.erase(it);

​ ++it;

​ }

​ return 0;

}

A.1 2 3 4 5 6 7 8 9

B. 1 2 3 4 6 7 8 9

C.程序运行崩溃

D.1 2 3 4 0 5 6 7 8 9

分析:程序在使用迭代器取值时,如果不等于0就进行打印,为0时不打印并删除当前节点,所以答案为 B

对于list有迭代器it, 当erase(it)后,说法错误的是( )

A.当前迭代器it失效

B.it前面的迭代器仍然有效

C.it后面的迭代器失效

D.it后面的迭代器仍然有效

分析:删除节点后,只有指向当前节点的迭代器失效了,其前后的迭代器仍然有效,因为底层为不连续空间,只有被删除的 节点才会失效, 所以答案为 C

下面有关vector和list的区别,描述正确的是( )

A.两者在尾部插入的效率一样高

B.两者在头部插入的效率一样高

C.两者都提供了push_back和push_front方法

D.两者都提供了迭代器,且迭代器都支持随机访问

A.vector在尾部插入数据不需要移动数据,list为双向循环链表也很容易找到尾部,因此两者在尾部插入数据效率相同

B.vector头部插入效率极其低,需要移动大量数据

C.vector由于在头部插入数据效率很低,所以没有提供push_front方法

D.list不支持随机访问

stack和queue

下列代码的运行结果是( )

void main()

{

​ stack S;

​ char x,y;

​ x=‘n’;y=‘g’;

​ S.push(x);S.push(‘i’);S.push(y);

​ S.pop();S.push(‘r’);S.push(‘t’);S.push(x);

​ S.pop();S.push(‘s’);

​ while(!S.empty())

​ {

​ x = S.top();

​ S.pop();

​ cout<<x;

​ };

​ cout<<y;

}

A.gstrin

B.string

C.srting

D.stirng

分析:S.push(x);S.push(‘i’);S.push(y); 入栈了字母“nig” 左边栈底 右边栈顶

S.pop();S.push(‘r’);S.push(‘t’);S.push(x); 字母g出栈,然后入栈字母“rtn”,此时栈数据 为"nirtn"

S.pop();S.push(‘s’);字母n出栈,s入栈,最终的栈数据为nirts

while(!S.empty()){} 栈不空出栈打印,按相反顺讯出栈,所以打印结果为:strin

cout<<y;最后还打印了字母g

所以答案为B

下列代码的运行结果是( )

void main()

{

​ queue Q;

​ char x,y;

​ x=‘n’;y=‘g’;

​ Q.push(x);Q.push(‘i’);Q.push(y);

​ Q.pop();Q.push(‘r’);Q.push(‘t’);Q.push(x);

​ Q.pop();Q.push(‘s’);

​ while(!Q.empty())

​ {

​ x = Q.front();

​ Q.pop();

​ cout<<x;

​ };

​ cout<<y;

}

A.gstrin

B.grtnsg

C.srting

D.stirng

分析:Q.push(x);Q.push(‘i’);Q.push(y); 入队数据为:nig 左边队头,右边队尾

Q.pop();Q.push(‘r’);Q.push(‘t’);Q.push(x); n出队,rtn入队,队里数据为:igrtn

Q.pop();Q.push(‘s’); i出队,s入队,队里数据为:grtns

while(!Q.empty()){} 队不空,在出队打印为:grtns

cout<<y; 最后在打印一个g

故答案为:B

一个栈的输入顺序是a,b,c,d,e则下列序列中不可能是出栈顺序是( )

A.e,d,a,c,b

B.a,e,d,c,b

C.b,c,d,a,e

D.b,c,a,d,e

分析:首先此题要保证入栈的顺序不能改变,其次,某个字母出栈前,必须把其栈顶的元素都要出栈

A:e要先出栈,就必须把a b c d e 全部入栈,然后e才能出栈,对于e d 的出栈没有问题,只是a要出栈,就必须c d 先出栈后,才能轮到a出栈,因此A是不可能得到的出栈顺序,其他答案可以自行验证

以下是一个二叉树的遍历算法,queue是FIFO队列,请参考下面的二叉树,根节点是root,正确的输出是( )

​ 1

​ 2 3

4 5 6 7

queue.push(root);
while(!queue.empty())
{node = queue.top();queue.pop();                             output(node->value)    //输出节点对应数字if(node->left)queue.push(node->left);if(node->right)queue.push(node->right);   
}

A.1376254

B.1245367

C.1234567

D.1327654

分析:此题是一个层次遍历的伪代码,能够看出是层次遍历,其结果就迎刃而解,答案 C


http://www.mrgr.cn/news/59886.html

相关文章:

  • 力扣每日一题3185. 构成整天的下标对数目 II
  • Vue 3.3 新增宏函数:`defineOptions` 和 `defineSlots` 简介
  • 萤石设备视频接入平台EasyCVR私有化视频平台变电站如何实现远程集中监控?
  • 【gRPC】什么是RPC——介绍一下RPC
  • 小程序视频SDK解决方案,提供个性化开发和特效定制设计
  • oracle imp和exp 导入不同库的用户和表空间
  • 计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-25
  • 多eSIM配置文件(MEP)
  • 网络搜索引擎Shodan(4)
  • C++线程池手写实现
  • 【Linux】MySQL主从复制
  • 宝安区石岩上排停车场(月卡350元)
  • 使用Python实现深度学习模型:智能极端天气事件预测
  • git合并上传小技巧
  • flutter vscode app 的输出在哪里
  • 新160个crackme - 084-slayer_crackme1
  • shutdown abort关库,真的可能起不来吗?
  • 一文彻底搞定MySQL中的JSON类型,效率飞起。
  • 软硬件开发面试问题大汇总篇——针对非常规八股问题的提问与应答(代码规范与生态管理)
  • shodan2---清风
  • 2025 - AI人工智能药物设计 - 中药网络药理学和毒理学的研究
  • opencv-platform实现人脸识别
  • 二十三、Python基础语法(包)
  • Upload-labs通关
  • Python 从入门到实战41(NumPy数值计算)
  • kNN 的花式用法(原来还能这么玩 kNN)