• 【笔试刷题训练】day_12


    我想说

    每天坚持一点点,坚持带来大改变
    今天是刷题的第_12天,加油!


    一、选择题

    在这里插入图片描述
    这道题存在多个错误

    错误一:在析构函数中调用delete this

    我们知道,使用delete会有两步:
    1. 调用析构函数释放对象中的资源
    2. 调用operator delete释放该对象

    题目中,在myClass的析构函数中delete this,那么首先就会调用~myClass(),然后再释放空间。但是调用~myClass()又会去delete this,每次调用delete this都会去调用~myClass,~myClass()又会去调用delete,互相调用形成死循环,从而导致栈溢出,程序崩溃!

    注意:只是在析构函数中delete this是可以通过编译的,但是运行的时候会形成死循环导致程序崩溃

    错误二:对this进行更改
    题目中,this = NULL这句代码是错误的,因为this的类型是类类型* const this,所以this是不能被更改的,this指向的内容可以被更改!所以因为this=NULL这句代码,会导致编译失败!

    错误三:delete是对new出来的对象进行释放,并不是所有的对象都是从堆上new出来的

    题目中,delete this,但是该对象并不一定是在堆上new出来的,对于myClass* ptr = new myClass,我们可以通过delete ptr进行释放。但是这个this所指的对象,可能就是在栈上创建的静态对象:myClass obj,采用delete对栈对象进行释放的话,首先会调用该对象的析构函数(这一步没问题),然后调用operator delete释放对象空间(这一步就会出现非法堆指针错误!)

    综上所述,所以最后程序的运行结果是:无法通过编译

    总结:
    在成员函数中调用delete this,会导致指针错误
    在析构函数中调用delete this,会导致堆栈溢出(死循环)

    在这里插入图片描述

    A: 对于一个类,如果我们不显式写构造函数,编译器会自动生成一个无参数的构造函数,但是如果我们自己显式定义了,这个无参数的默认构造函数就不会生成。所以有没有无参数的构造函数取决于我们自己。
    B: 误区:并不是每一个类都有一个拷贝构造函数!虽然对于拷贝构造函数,我们不显式定义编译器会自动生成一个拷贝构造函数,但是我们可以人为的让其没有拷贝构造函数。看如下代码:
    class A{
    public:
      A(){};
      ~A();
       A(A&);  //声明一个拷贝构造函数,编译器也不会生成了!
    }
    在main函数中调用其拷贝构造,程序运行结果是:链接错误,无法找到拷贝构造函数!也就是说,编译器看到有用户显式写的拷贝构造的声明之后,便不会生成默认的拷贝构造函数了,我们可以通过声明但不定义拷贝构造,从而让该类没有拷贝构造

    补充知识:C++11中有专门的方式可以让一个类没有拷贝构造:
    A(A&) = delete; //即在函数声明后面加一个 =delete,告诉编译器不要生成他的默认函数!
    此时如果在主函数中调用该类的拷贝构造,就会提示:尝试引用已删除的函数

    总结:写一个没有拷贝构造的类:
    1.构造函数只给声明不给定义
    2.使用C++11的 =delete,不让编译器自动生成默认拷贝构造

    C:拷贝构造也是一种构造函数,可以存在重载!所以每个类可以有多个拷贝构造函数!
    D:析构函数没有参数,所以无法重载,每个类只能有一个析构函数!


    在这里插入图片描述
    A:堆的大小取决于操作系统给堆分配多少内存,栈的内存一般很小,正确√
    B:new/delete是在堆上随机申请内存,所以频繁申请很容易产生内存碎片问题。而栈的是由编译器自动管理,对于使用完的变量会自动进行销毁,所以不存在此问题!
    C:堆只能动态分配,×
    D:堆只能动态分配,栈可以动态也可以静态 √

    详细的请见我这篇文章:👉6堆栈那些事儿~

    二、编程题

    1.二进制插入

    👉 题目链接

    思路1:拿到m的每一位插入到n的对应位置

    即对每一位利用 | 运算

    class BinInsert {
    public:
        int binInsert(int n, int m, int j, int i) {
            // write code here
            //把m插入到n的第j到i位
            int index = 0;
            for(int k = j;k<=i;++k)
            {
                //(m>>index)&1拿到m的每一位
                // <
                // 然后|= 就是把m的对应位置插入到n的对应位置
                n |= ((1 & (m>>index)) << k);
                ++index;
            }
            return n;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    思路2:m直接左移j位,整体或运算

    class BinInsert {
    public:
        int binInsert(int n, int m, int j, int i) {
            // write code here
           return n | (m<<j);
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2. 查找组成一个偶数最接近的两个素数

    👉 题目链接

    给一个偶数n,我们要找组成该偶数的最接近的两个素数

    我们可以从 n/2 处开始找,left为左半部分,right为右半部分

    如果left和right都是素数,那么就输出这两个数

    否则,–left,++right

    #include
    #include
    using namespace std;
    //判断是否为素数
    bool ispri(int num)
    {
        for(int i = 2;i<=sqrt(num);++i)
        {
            if(num%i==0)
            {
                return false;
            }
        }
        return true;
    }
    int main()
    {
        int n;
        cin >> n;    //偶数
        //找到组成n的两个最小素数
        //24:12*2 -> 11 13
        //18:9*2 -> 8 10 -> 7 11 √
        
        //思路:从中间向左右找
        int left = n/2;
        int right = n/2;
        //有一个不是素数,就继续循环
        while(!ispri(left) || !ispri(right))
        {
            --left;
            ++right;
        }
        cout << left <<endl;
        cout << right << endl;
        
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

  • 相关阅读:
    ASP.NET Core - 选项系统之选项验证
    ESP32烧写Arduino编译的固件
    大学物理·第8章【电磁感应、电磁场】
    【多模态融合】TransFusion学习笔记(1)
    MSP432学习笔记7:定时器A中断
    基于Spring Boot+Vue的健身房管理系统(协同过滤算法、功能非常多)
    MySQL read 查询语句7 复制 去重 外连接
    L46.linux命令每日一练 -- 第七章 Linux用户管理及用户信息查询命令 -- w和who
    Java学习笔记37——网络编程01
    ES6~ES13新特性(一)
  • 原文地址:https://blog.csdn.net/K_04_10/article/details/127565912