复习c++基础知识(2)

7 篇文章 0 订阅
  1. C++程序,在函数体中定义的下列变量,函数结束后其内存空间被自动释放的有(BD):
A. 使用new关键字创建的数组,例如: int* a = new int[10];
B. 定义的数组,例如: int a[10];
C. 通过new关键字创建的类对象,例如: A *a = new A();
D. 使用智能指针指向的类对象,并且该指针没有被函数以外的地方使用
例如: std::shared_ptr<A> p = std::make_shared<A>();
class A {
public:
    A(std::string inname) { name = inname; }
    ~A() { cout <<this->name<<" released" << endl; }
    int age;
    std::string name;
};
// 测试 A
int* test_AC()
{
    int* a = new int[10];
    for (int i = 0; i < 5; i++)
    {
        a[i] = i + 10;
    }
    return a;
}
void test21()
{
    int* tmp = test_AC();
    cout << "----------" << endl;
    for (int i = 0; i < 5; i++)
    {
        cout << tmp[i] << endl;
    }
	//测试C,函数结束后应该也没被放,如果释放了就打印Release
    A* a = new A("me");
    //测试D,函数结束后释放了
    std::shared_ptr<A> p = std::make_shared<A>("ass");
}
int main()
{
    test21();
    getchar();
}

输出结果:

在这里插入图片描述

  1. c++,在类中可以声明多个同名函数,这就是类成员函数的重载(overload),以下对构造函数和析构函数描述正确的是(A):
A.构造函数可以重载,析构函数不能重载
B.构造函数不能重载,析构函数可以重载
C.构造函数可以重载,析构函数可以重载
D.构造函数可重载,析构函数也不可重载
因为构造函数可以有多个且可以带参数,而析构函数只能有一个,且不能带参数
  1. 对于通常Debug Build和Release Build,正确的说法(AB)
A.发布程序时,应该使用Release Build
B.通常Debug构建出的程序便利于进行单步调试
C.assert()断言,通常只在Release Build时起作用
D.两种模式下,编译器对程序进行的优化通常是相同的
  1. TCP/IP(IPv4)协议下,ip是几 () 位(bit)的二进制.
A.16    B.32    C.8    D.4
//举例
255.255.255.255
bitset<9> bits(255)
cout<<bits<<endl; //结果11111111
  1. 用链表表示线性表的优点是(A)
A.便于插入与删除
B.数据元素在内存中的物理顺序与逻辑顺序相同
C.花费的存储空间一定比顺序表少
D.便于随机存取
  1. 以下说法中正确的有(ABD)
A.UTF-8是一种可变长度字符编码
B.UTF-8可以直接兼容ASCLL
C.ASCLL编码中,每个字符的长度都是2个字节
D.为了方便使用,ASCLL编码中字符'0'的编码恰好为0

找到几个解释的博客
博客1
博客2
it屋3

  1. 将单链表最后一个节点的指针域指向表头节点,就得到了单链形式的循环链表,并成为循环单链表
    在循环单链表中,查找某个节点的后继和前驱的时间复杂度分别是(
    C )
A. O(n)O(1)
B. O(1)O(1)
C. O(1)O(n)
D. O(n)O(n)

个人觉得是 O(1)和O(n),不太确定

  1. 看代码结果
void test22()
{
    int a[10];
    int i = 10;
    cout << a[10] << endl;
}
//可以正常生成程序,但是运行时可能会报错
  1. 还是看代码
void foo();
int main()
{
    foo();
    getchar();
}

上述程序,下面表达正确的是(D)

A. 可以正常生成程序,但是运行时报错
B. 在生成程序的预处理阶段,会报错
C. 在生成程序的编译阶段,会报错
D. 在生成程序的链接阶段,会报错

在这里插入图片描述
如图可知:错误发生在 LINK(链接阶段)
参考解释的博客1
参考解释的博客2
预处理阶段:
宏的替换,删除注释,处理预处理指令
编译阶段:
词法分析(类型检测),
语法分析(代码语法检测),
语义分析(单词,短语,语义特征) ,
代码优化(修辞,文本编辑),
代码生成(生成汇编语言)
汇编阶段
汇编语言代码翻译成机器指令
链接程序
将有关的目标文件彼此相链接,也在一个文件中引用符号同该符号在另一个文件中的定义连接起来.

  1. 在类的继承中,以下属于良好设计的是(BCD)
A. 基类的构造函数,通常应该定义为虚函数
B. 基类的析构函数,通常应该定义为虚函数
C. 在派生类中覆盖基类的虚函数时,使用override关键字
D. 当基类中虚函数会被派生类覆盖时,在基类中使用final关键字
A的解释:
构造函数为什么不能是虚函数呢?
首先需要了解 vptr指针和虚函数表的概念,以及这两者的关联。
vptr指针指向虚函数表,执行虚函数的时候,会调用vptr指针指向的虚函数的地址。
当定义一个对象的时候,首先会分配对象内存空间,然后调用构造函数来初始化对象。
vptr变量是在构造函数中进行初始化的。又因为执行虚函数需要通过vptr指针来调用。
如果可以定义构造函数为虚函数,那么就会陷入先有鸡还是先有蛋的循环讨论中
B的解释: 
1. 当基类派生一个派生类并声明一个派生类时,
先调用基类构造函数,后调用派生类构造函数; 释放派生类时,先调用派生类的析构函数,后调用基类析构函数
2. 当使用基类指针new一个派生类对象时: 释放对象时,若基类为虚函数,则先调用派生类的析构函数后调用基类析构函数,
若不是虚析构函数,则直接调用基类析构函数.
C的解释:
在声明需要重写的函数后,加关键字 override
这样,即使不小心漏写了虚函数重写的某个苛刻条件,也可以通过编译器的报错,快速改正错误
https://blog.csdn.net/weixin_42905141/article/details/94405090
D的解释:
而final关键字为我们提供了一种控制手段,用来阻止子类重写自身的虚函数,
final通常只在继承关系的“中途”终止派生类的重载中有意义
  1. 关于进程/线程,以下说法正确的有(BC)
A. 进程间通信通常比线程间通信更快
B. 一个进程可以有多个线程,这些线程共享内存空间
C. 创建进程的开销大于创建线程
D. 子进程可以直接访问父进程
A的解释:
进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程
B的解释:
一个进程(.exe),每一个进程都有它自己的地址空间,里面很多函数,类对象,都用的相同资源空间
C的解释:
线程执行开销比较小,但是不利于资源的管理和保护
D的解释:
每个进程都是一个独立的地址空间(,,虚拟内存,文件句柄...)

进程线程解释参考博客链接

  1. 如果Sub类时Base类的子类(Sub继承Base),一下属于良好设计的是(BCD)
A. 在任何需要使用Sub类的对象的场合,应该都可以使用Base类的对象
B. 在任何需要使用Base类的对象的场合,应该都可以使用Sub类的对象
C. Sub类和Base类,符合"has a"的关系,"Sub has a Base"
D. Sbu类和Base类,符合"is a"的关系,"Sub is a Base"

不太懂: 看别人的解释

  1. 对于这函数,说法正确的是(D)
A. 该函数永远返回true
B. 该函数永远返回false
C. 当a+b不溢出时,该函数一定返回true
D. 即时a+b鼻翼处,该函数仍然不一定返回true

浮点型变量跟0比较需要用到精度EPSILON, 指的是浮点数可表示的最小值
上一期第一题就是通常方法
编译了一下,如图:
在这里插入图片描述

  1. 关于使用c++进行文件读写,以下说法中正确的有(ABD)
A. 文件可以分为文本文件(text)和二进制文件(binary)
B. 通过ofstream向磁盘中一个文件进行put()操作,该文件的长度会马上增加1
C. 打开文件时的标记(flags),:ios::app,ios::out等,可以通过&运算符组合在一起
D.以单纯的out模式打开文件,如果该文件已经存在,则原有的文件内容会被丢弃
A的解释:
的确是这样的.ios::binary 就是读取成二进制,不加就是文本
B的解释:
put()函数向流写入一个字符,其原型是ofstream &put(char ch),使用也比较简单,如file1.put(’c’);就是向流写一个字符’c’
C的解释:
使用|这个符号
D的解释:
//按顺序执行test_out1();test_out2()
//结果文件里是m覆盖
void test_out1()
{
    ofstream outfile(".\\out.txt");
    if (!outfile.is_open())
    {
        cout << "file open failed" << endl;
        return;
    }
    outfile.put('m');
    string mm("我的妈呀");
    outfile << mm.c_str() << endl;
}
void test_out2()
{
    ofstream outfile(".\\out.txt");
    if (!outfile.is_open())
    {
        cout << "file open failed" << endl;
        return;
    }
    outfile.put('m');
    string mm("覆盖");
    outfile << mm.c_str() << endl;
}

在这里插入图片描述

  1. 关于static_cast/dynamic_cast,以下说法中正确的有(AC)
A. static_cast是在编译时进行数据类型转换
B. static_cast是在运行时进行数据类型转换
C. dynamic_cast对指针进行转换时,如果失败,会返回空指针
D. dynamic_cast对指针进行转换时,如果失败,程序会崩溃
A的解释:
编译时类型转换.
简单截断操作,intchar,int的低8位复制到char8位中,抛弃高位
多用于指针转换
C的解释:
dynamic_cast主要用于类层次结构中父类和子类之间指针和引用的转换,
由于具有运行时类型检查,因此可以保证下行转换的安全性,何为安全性?
即转换成功就返回转换后的正确类型指针,如果转换失败,则返回NULL

参考说明链接

  1. 下述代码片段中,T是已经定义好的一个class,上面代码段中,存在的问题是(BC)
    A* p = new A[10];
    delete[] p;
A. 编译错误
B. 运行时崩溃
C. 潜在内存泄漏
D. 没有问题

如图:在这里插入图片描述

  1. 下面哪一方法可以判断出一个有向图是否有环(回路).(B)
A.求节点额度
B.拓扑排序
C.求最短路径
D.求关键路径
  1. 关于STL中的stl::vector,以下说法中正确的有(AB)
A.stl::vector,中所有元素被存储在一块连续的内存空间
B.当向stl::vector添加元素时,vector可以根据需求自动扩大容量
C.如果用stl::vector存储类对象的普通指针(例如A *p=new A();),当vector被销毁时,这些对象的析构函数会被调用
D.可以向stl::vector中任意位置添加元素,并且复杂度为O(1)
A的解释:
对的.不解释
B的解释:
对的,不解释
C的解释:
无法调用指针对象的析构函数    https://www.it1352.com/466237.html

D的解释:

  1. 关于c++中函数参数传递,以下说法中正确的有:(ABCD)
A. 按引用传递可以减少不必要的对象复制
B. 按引用传递对象(A& a)通常比传递对象的指针(A *a)更加安全
C.按引用传递对象时,(A& a),不能使用const关键字进行修饰
D.按引用传递,可以用于函数需要有多个值需要输出的场合.
B的解释:
编译时提供引用的检测,指针的话还需要判断是否是空指针NULL
C的解释:
因为用引用作为参数就是为了修改它,const就不能修改了
D的解释:
scanf_s常用fscanf也是挺方便

在这里插入图片描述

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路途遥远gg

帮到你了就好

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值