#C++ 笔记三

news2024/9/20 8:48:29

 七、异常处理

1.概念

异常是程序在执行期间产生的问题。

C++异常是指在程序运行时发生的特殊情况,比如下标越界等。

异常提供了一种转移程序控制权的方式。

2.抛出异常

throw语句的操作数可以是任意表达式,表达式结果的类型决定了抛出异常的类型。

抛出的异常是抛出到函数调用的位置。

#include <iostream>
using namespace std;


double division(double a,double b)
{
    if(b == 0)
    {
        string text("除数等于0!");
        throw text; // 抛出一个std::string
    }
    return a/b;
}

double input()
{
    cout << "input开始执行" << endl;
    double a;
    double b;
    cout << "请输入两个浮点型:" << endl;
    cin >> a >> b;
    double c = division(a,b);   // 1text 对象在这(无人处理)
    cout << "input执行结束" << endl;
    return c;
}

int main()
{
    cout << "程序开始执行" << endl;
    cout << input() << endl;    // 2text 对象在这(无人处理)

    cout << "程序执行结束" << endl;
    return 0;
}

3、捕获异常

try代码抛出一个异常,捕获异常使用catch代码块。


#include <iostream>
using namespace std;


double division(double a,double b)
{
    if(b == 0)
    {
        string text("除数等于0!");
        throw text; // 抛出一个std::string
    }
    return a/b;
}

double input()
{
    cout << "input开始执行" << endl;
    double a;
    double b;
    cout << "请输入两个浮点型:" << endl;
    cin >> a >> b;
    double c;
    try // 尝试执行代码块
    {
        c = division(a,b);
    }
    catch(string &e) // catch小括号中要写抛出异常的类型(类型跟抛出的类型不符合,会出现捕获不到的情况)
    {
        // 验证异常对象
        cout << e << endl;

        // 补救措施
        return 0;
    }

    cout << "input执行结束" << endl;
    return c;
}

int main()
{
    cout << "程序开始执行" << endl;
    cout << input() << endl;

    cout << "程序执行结束" << endl;
    return 0;
}

上述代码中可能会出现的几种情况:

1.无异常抛出,此时程序正常执行,不进入catch块

2.异常抛出,正确捕获,此时程序执行进入catch块。

3.异常抛出,错误捕获(捕获类型不对),此时程序仍然会向上抛出寻求正确捕获,如果每一层都没有正确捕获,此时程序仍然执行终止。

4、标准异常体系

C++给常见的异常类型进行了定义和分类,引入#include<stdexcept>头文件后进行使用。

这个体系还是太薄弱,因此可以对齐进行拓展。

自定义一个类型,继承自某个异常类型即可。

catch块可以匹配基类异常类型,提高匹配成功率,但是会降低匹配的精度

5、多重捕获

#include <iostream>
#include <stdexcept>
using namespace std;
// 继承自exception
class MyException:public exception
{
public:
    // 覆盖what函数
    // throw():异常规格说明
    // 表示此函数不会抛出任何的异常
   const char* what()const throw()
   {
        return "自定义类型异常";
   }
};

void show(string a,string b)
{
    if(a == "#" || b == "#")
    {
        throw MyException();
    }
    cout << a << b << endl;
}

int main()
{
    int type;
    cout << "请输入1或2或其他数字" << endl;
    cin >> type;
    try
    {
        if(type == 1)
        {
            string s = "fdfd";
            cout << s.at(100) << endl;
        }
        else if(type == 2)
        {
            throw overflow_error("异常2");
        }
        else
        {
            show("#","1211");
        }
    }
    catch(out_of_range &e)
    {
        cout << e.what() << endl;
    }
    catch(overflow_error &e)
    {
        cout << e.what() << endl;
    }
    catch(MyException &e)
    {
        cout << e.what() << endl;
    }
    cout << "程序正常运行结束" << endl;
    return 0;
}

6、粗略捕获

除了可以直接捕获异常类型外,也可以捕获异常的基类,甚至所有异常类型。

#include <iostream>
#include <stdexcept>
using namespace std;


int main()
{
    string s = "hello";
    try
    {
        cout << s.at(100) << endl;
    }
    catch(logic_error &e)
    {
        cout << e.what() << endl;
    }
    cout << "程序正常执行结束" << endl;

    return 0;
}

粗略捕获与多重捕获同时使用,此时要注意捕获的顺序,为派生类异常优先。

#include <iostream>
#include <stdexcept>
using namespace std;

int main()
{
    int type;
    cout << "请输入1或2、3或其他数字" << endl;
    cin >> type;
    try
    {
        if(type == 1)
        {
            throw invalid_argument("异常1");
        }
        else if(type == 2)
        {
            throw overflow_error("异常2");
        }
        else if(type == 3)
        {
            throw length_error("异常3");
        }
        else
        {
            throw out_of_range("异常4");
        }
    }
    catch(exception &e)
    {
        cout << "exception" <<e.what() << endl;
    }
    catch(out_of_range &e)
    {
        cout << e.what() << endl;
    }
    catch(overflow_error &e)
    {
        cout << e.what() << endl;
    }
    catch(length_error &e)
    {
        cout << e.what() << endl;
    }
    catch(invalid_argument &e)
    {
        cout << e.what() << endl;
    }

    cout << "程序正常运行结束" << endl;
    return 0;
}

使用...可以捕获所有类型,但是不推荐,更推荐使用或者建立标准异常体系。

#include <iostream>
#include <stdexcept>
using namespace std;
double division(double a,double b)
{
    if(b == 0)
    {
        string text("除数等于0!");
        throw text; // 抛出一个std::string
    }
    return a/b;
}


int main()
{
    int type;
    cout << "请输入1或2、3或其他数字" << endl;
    cin >> type;
    try
    {
        if(type == 1)
        {
            throw invalid_argument("异常1");
        }
        else if(type == 2)
        {
            throw overflow_error("异常2");
        }
        else if(type == 3)
        {
            throw length_error("异常3");
        }
        else if(type == 4)
        {
            division(3.3,0);
        }
        else
        {
            throw out_of_range("异常4");
        }
    }
    catch(exception &e)
    {
        cout << "exception" <<e.what() << endl;
    }
    catch(out_of_range &e)
    {
        cout << e.what() << endl;
    }
    catch(overflow_error &e)
    {
        cout << e.what() << endl;
    }
    catch(length_error &e)
    {
        cout << e.what() << endl;
    }
    catch(invalid_argument &e)
    {
        cout << e.what() << endl;
    }
    catch(...)
    {
       cout << "...异常" << endl;
    }

    cout << "程序正常运行结束" << endl;
    return 0;
}

八、智能指针

概念

堆内存的对象需要手动delete销毁,如果忘记使用delete销毁就会造成内存泄漏。

所以C++在ISO 98标准中引入了智能指针的概念,并在ISO11中趋于完善。

使用智能指针可以让堆内存对象具有占内存对象的特性,原理是给需要手动回收的堆内存对象套上一层栈内存的模板类对象即可。

C++中有四种智能指针:

  • auto_ptr(自动指针)(C++98,已废弃)
  • unique_ptr(唯一指针)(C++11)
  • shared_ptr(共享指针)(C++11)
  • weak_ptr(虚指针)(C++11)

使用智能指针的使用需要引入头文件#include<memory>

1 auto_ptr(熟悉)

 
 
 
#include <iostream>
#include <memory>
using namespace std;

class Test
{
private:
    string s;
public:
    Test(string s):s(s)
    {
        cout << s << "构造函数" << endl;
    }

    ~Test()
    {
        cout << s << "析构函数" << endl;
    }

    void show()
    {
        cout << s << "执行程序" << endl;
    }
};

int main()
{
    {
        Test *t1 = new Test("A");
        // 创建一个栈内存智能指针对象ap1
        auto_ptr<Test> ap1(t1); // ap1 管理t1

        // 取出被管理的堆内存对象,并调用show成员函数
        ap1.get()->show();
        // 释放ap1智能指针堆t1对象的控制权
        ap1.release();
        // 释放控制权并销毁资源对象
//        ap1.reset();

        // 创建B堆对象,A对象销毁,管理B对象
//        ap1.reset(new Test("B"));

//        delete t1;
        cout << "局部代码块执行结束" << endl;
    }   // 当ap1智能指针被销毁时,t1堆内存对象也销毁
    cout << "程序运行结束" << endl;
    return 0;
}

由于成员变量存在指针类型,因此拷贝构造函数与赋值运算符重载的使用会出现问题,与浅拷贝不同的是,auto_ptr的复制语义会引起对象控制权转移的问题。

 
 
 
#include <iostream>
#include <memory>
using namespace std;

class Test
{
private:
    string s;
public:
    Test(string s):s(s)
    {
        cout << s << "构造函数" << endl;
    }

    ~Test()
    {
        cout << s << "析构函数" << endl;
    }

    void show()
    {
        cout << s << "执行程序" << endl;
    }
};

int main()
{
    {
        auto_ptr<Test> ap1(new Test("A"));
        auto_ptr<Test> ap2(ap1);    // 调用拷贝构造函数
        cout << ap1.get() << " " << ap2.get() << endl; // 0 0x732758

        auto_ptr<Test> ap3 = ap2;   // 调用拷贝构造函数
        cout << ap1.get() << " " << ap2.get() << " " << ap3.get() << endl; // 0 0 0x1022758

        auto_ptr<Test> ap4;
        ap4 = ap3;  // 赋值运算符重载
        cout << ap1.get() << " " << ap2.get() << " " << ap3.get() << " " << ap4.get() << endl; // 0 0 0 0xf42758
    }
    cout << "程序运行结束" << endl;
    return 0;
}

2. unique_ptr(熟悉)

作为堆auto_ptr的改进,unique_ptr对其他持有的资源对象具有唯一的控制权,即不可以通过常规的复制语法转移或拷贝资源对象的控制权。

但是unique_ptr可以通过特殊的语法来实现控制权转移的效果。

 
 
 
#include <iostream>
#include <memory>
using namespace std;

class Test
{
private:
    string s;
public:
    Test(string s):s(s)
    {
        cout << s << "构造函数" << endl;
    }

    ~Test()
    {
        cout << s << "析构函数" << endl;
    }

    void show()
    {
        cout << s << "执行程序" << endl;
    }
};

int main()
{
    {
        unique_ptr<Test> up1(new Test("A"));
        unique_ptr<Test> up2(move(up1));    // 调用拷贝构造函数
        cout << up1.get() << " " << up2.get() << endl; // 0 0x732758

        unique_ptr<Test> up3 = move(up2);   // 调用拷贝构造函数
        cout << up1.get() << " " << up2.get() << " " << up3.get() << endl; // 0 0 0x1022758

        unique_ptr<Test> up4;
        up4 = move(up3);  // 赋值运算符重载
        cout << up1.get() << " " << up2.get() << " " << up3.get() << " " << up4.get() << endl; // 0 0 0 0xf42758
    }
    cout << "程序运行结束" << endl;
    return 0;
}

3. shared_ptr掌握)

unique_ptr对资源具有独占性,多个shared_ptr对象可以共享资源。

shared_ptr有两种创建方式:

两种创建方式的区别在于后者是一步实现(创建资源对象+关系绑定),前者分为两步完成(先创建资源,再绑定关系)。

后者的优点:

  • 完全性更好
  • 性能更好

后者的缺点:

  • 资源释放效率低

每多一个shared_ptr对资源进行管理,引用计数+1,每个指向该对象的shared_ptr智能指针对象在销毁时,引用计数将-1。最后一个shared_ptre对象销毁时,计数清零,资源对象销毁。

 
 
 
#include <iostream>
#include <memory>
using namespace std;

class Test
{
private:
    string s;
public:
    Test(string s):s(s)
    {
        cout << s << "构造函数" << endl;
    }

    ~Test()
    {
        cout << s << "析构函数" << endl;
    }

    void show()
    {
        cout << s << "执行程序" << endl;
    }
};

int main()
{
    shared_ptr<Test> sp3;
    {
        shared_ptr<Test> sp1 = make_shared<Test>("A");
        cout << "引用计数" << sp1.use_count() << endl; // 引用计数 1

        shared_ptr<Test> sp2(sp1); // 拷贝构造函数
        cout << "引用计数:" << sp2.use_count() << endl; // 引用计数:2

        sp3 = sp2;
        cout << "引用计数:" << sp3.use_count() << endl; // 引用计数:3
    }
    cout << "引用计数:" << sp3.use_count() << endl; // 1
    sp3.get()->show();
    cout << "程序运行结束" << endl;
    return 0;
}

4. weak_ptr熟悉)

weak_ptr是一个不控制资源对象的智能指针,也不会影响资源的引用计数,其主要的目的是协助shared_ptr的工作。

通过weak_ptr的构造函数,参数传入一个持有资源对象的shared_ptr对象或weak_ptr对象,即可创建。

weak_ptr与资源独享呈现弱相关性,因此不支持 get等函数直接操作资源对象。

 
 
 
#include <iostream>
#include <memory>
using namespace std;

class Test
{
private:
    string s;
public:
    Test(string s):s(s)
    {
        cout << s << "构造函数" << endl;
    }

    ~Test()
    {
        cout << s << "析构函数" << endl;
    }

    void show()
    {
        cout << s << "执行程序" << endl;
    }
};

int main()
{
    weak_ptr<Test>wp3;
    {
        shared_ptr<Test> sp1 = make_shared<Test>("A");
        weak_ptr<Test> wp1 = sp1;   // 构造函数
        cout << sp1.use_count() << endl;    // 1
        cout << wp1.use_count() << endl;    // 1

        weak_ptr<Test> wp2(wp1);
        cout << wp2.use_count() << endl;    // 1

        // 从weak_ptr中得到一个持有资源对象的shared_ptr对象
        shared_ptr<Test> sp2 = wp1.lock();
        cout << sp2.use_count() << endl; // 2

        wp3 = wp1;
        cout << wp3.use_count() << endl;    // 2
    }
    cout << wp3.use_count() << endl;    // 0

    if(wp3.expired())
    {
        cout << "无法使用lock函数" << endl;
    }

    cout << "程序运行结束" << endl;
    return 0;
}

5. 思考题了解)

手写一个共享指针SharedPtr。要求实现:

  • 构造函数
  • 拷贝构造函数
  • 复制运算符重载
  • get()函数
  • use_count函数
  • reset函数
  • 析构函数

 
 
 
#include <iostream>
#include <memory>
using namespace std;

template<class T>
class SharedPtr
{
private:
    T *res = NULL;  // 资源指针
    int *count = NULL;  // 引用计数

public:
    SharedPtr(T *t):res(t),count(new int(1)){}

    // 拷贝构造函数
    SharedPtr(const SharedPtr &sp):res(sp.res),count(sp.count)
    {
        (*count)++; // 计数+1
    }

    // 赋值运算符重载
    SharedPtr& operator =(const SharedPtr &sp)
    {
        if(&sp != this)
        {
            // 销毁原来的资源
            reset();
            res = sp.res;
            count = sp.count;
            (*count)++; // 计数+1
        }
        return *this;
    }

    void reset()
    {
        (*count)--; // 计数-1
        if(*count == 0)
        {
            delete res;
            delete count;
        }
        res = NULL;
        count = NULL;
    }

    T* get()const
    {
        return res;
    }

    int use_count()const
    {
        return *count;
    }

    ~SharedPtr()
    {
        reset();
    }
};



class Test
{
private:
    string s;
public:
    Test(string s):s(s)
    {
        cout << s << "构造函数" << endl;
    }

    ~Test()
    {
        cout << s << "析构函数" << endl;
    }

    void show()
    {
        cout << s << "执行程序" << endl;
    }
};

int main()
{
    SharedPtr<Test> sp1(new Test("A"));
    sp1.get()->show();
    cout << sp1.use_count() << endl;

    SharedPtr<Test> sp2(sp1);
    cout << sp2.use_count() << endl;

    SharedPtr<Test> sp3(new Test("B"));
    cout << sp3.use_count() << endl;    // 1

    sp3 = sp2;  // 赋值运算符重载
    sp3.get()->show();
    cout << sp3.use_count() << endl;

    return 0;
}

九、其他

1. nullptr(熟悉)

NULL在源码中就是一个0,因此可能会存在一些二义性的问题。

 
 
 
#include <iostream>
using namespace std;

void func(int a)
{
    cout << "a="<< a << endl;
}

void func(int *b)
{
    cout << "b=" << b << endl;
}

int main()
{
    func(NULL); // a=0

    return 0;
}

在C++11中使用nullptr代替NULL,作为空指针的表示方式。

 
 
 
#include <iostream>
using namespace std;

void func(int a)
{
    cout << "a="<< a << endl;
}

void func(int *b)
{
    cout << "b=" << b << endl;
}

int main()
{
    func(nullptr);  // b=0
    return 0;
}

2. 类型推导(熟悉)

使用auto关键字可以推导类型,C++11引入的。

 
 
 
#include <iostream>
using namespace std;


int main()
{
    auto i = 10;    // i的类型被推到为整形(int)
    cout << i << endl;

    auto i2 = 19.3; //  i2的类型被推导为浮点型(double)
    cout << i2 << endl;

    auto i3 = new auto(10); // i3 的类型被推导为int *
    cout << *i3 << endl;

    auto i4 = "hello";
    cout << i4 << endl;

    auto i5 = 'a';
    cout << i5 << endl;

    return 0;
}

decltype可以推导表达式的类型,需要注意的是,decltype只会分析表达式的类型,不会计算表达式的值。

 
 
 
#include <iostream>
using namespace std;


int main()
{
    auto x = 1; // 整形
    auto y = 2; // 整形

    decltype(x*y+123) z = 8888.87; // int * int + int = int
    cout << z << endl;

    return 0;
}

3. 初始化列表(掌握)

C++11中引入了列表初始化(初始化列表、通用统一初始化、一致性初始化)语法,可以使用{}对对象进行初始化。

 
 
 
#include <iostream>
#include <array>
#include <vector>
using namespace std;


class Student
{
private:
    string name;
    int age;
public:
    Student(string name,int age):name(name),age(age){}

    void show()
    {
        cout << name << " " << age<< endl;
    }

};

int main()
{
    array<int,5> arr1 = {1,2,3,4,5};
    for(int i:arr1)
    {
        cout << i << " ";   // 1 2 3 4 5
    }
    cout << endl;

    vector<int> vec1 = {1,2,3};
    for(int i:vec1)
    {
        cout << i << " ";   // 1 2 3
    }
    cout << endl;

    int arr3[3] = {1,2,4};
    for(int i:arr3)
    {
        cout << i << " ";   // 1 2 4
    }
    cout << endl;

    int a{};
    cout << a << endl;  // 0

    Student s = {"张三",10};
    s.show();

    return 0;
}

4. 面试题(重点)

【面试题】C++11学过的新特性有那些?

  1. 智能指针(后三个)
  2. array
  3. for-each
  4. 初始化列表
  5. nullptr
  6. 类型推导
  7. 继承构造
  8. override
  9. 类型转换(四种cast函数)

5. 进制输出(了解)

C++11可以对整数进行不同进制的输出。

 
 
 
#include <iostream>

using namespace std;



int main()
{
    // 为了区分不同的进制,可以增加进制显式功能,此功能设定持久
    cout << showbase;
    // 默认为10进制
    cout << dec << 1234 << endl; // 1234
    cout << oct << 1234 << endl; // 2322
    // 输出进制的设定是持久的
    cout << 9 << endl;  // 11
    cout << hex << 256 << endl;  // 100

    // 取消进制显式功能
    cout << noshowbase;
    cout << 16 << endl; // 10
    return 0;
}

6. 设定输出域宽度(了解)

可以使用setw()来制定一个整数或者一个字符串输出占用的域宽度。

  • 当设定域宽度小于数据本身时,仍然会显式为数据本身的宽度。
  • 当设定域宽度大于数据本身时,会显式未设定的宽度。

需要注意的是,输出域的宽度不是持久的,需要每次输出设定。

 
 
 
#include <iostream>
#include <iomanip>
using namespace std;


int main()
{
    // 仍然会按照实际的宽度输出
    cout << setw(5) << 123456 << setw(5) << 123456 << endl;

    // 使用输出域宽度
    cout << setw(10) << 123456 << setw(10) << 123456 << endl;

    cout << setw(10);
    cout << 123456 << endl;

    cout << 123456 << endl; // 输出域无效,因为输出域只能作用于下一行

    cout << setw(10);
    cout << 123456 << endl;

    return 0;
}

7. 文件IO(了解)

 
 
 
#include <iostream>
#include <fstream>  // 文件流头文件
using namespace std;


int main()
{
    // 文件输入流对象,用于读取数据
    // 参数1:读取的路径
    // 参数2:读取的方式二进制
    ifstream ifs("D:\\meeting_01.mp4",ios_base::binary);
    if(!ifs)
    {
        cout <<  "文件或路径不存在" << endl;
        return -1;
    }

    // 文件输出流对象,用于输出数据
    // 参数1:写出的路径
    // 参数2:写出方式二进制
    ofstream ofs("C:\\Users\\Administrator\\Desktop\\meeting_01.mp4",ios_base::binary);
    if(!ofs)
    {
        cout << "输出路径不存在" << endl;
        return -1;
    }
    // 把文件指针移动输入流尾部
    // 参数1:相对偏移量
    // 参数2:移动的位置
    ifs.seekg(0,ios::end);
    cout << "文件总大小:" << ifs.tellg() << "bytes" << endl;

    // 把文件指针移动回头部
    ifs.seekg(0,ios::beg);

    // 准备一个buffer
    char buf[2048];
    long long hasResd = 0;  // 已经读取的文件大小

    // 循环读写
    while(ifs)
    {
        // 读取固定的长度到buf中
        ifs.read(buf,2048);

        // 读取设定长度的数据到目标位置
        // 参数1:数据来源
        // 参数2:输出的数据量ifs.gcount()为上一次文件指针的偏移量
        ofs.write(buf,ifs.gcount());
        hasResd += ifs.gcount();
        cout << "已经拷贝的字节数:" << hasResd << endl;
    }

    // 收尾
    ifs.close();
    ofs.flush();    // 清空缓存区
    ofs.close();
    cout << "文件拷贝完成!!!!" << endl;

    return 0;
}

考试:

考试时长1.5小时

15~选择题(45)

5~简单题

10 填空题

1 编程题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2086989.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Elasticsearch Suggesters API详解与联想词自动补全应用

Elasticsearch Suggesters API详解与联想词自动补全应用 引言Elasticsearch Suggesters1. Term Suggester实现步骤示例 2. Phrase Suggester示例 3. Completion Suggester创建映射和插入数据查询示例 4. Context Suggester示例 Completion Suggester1. 工作原理2. 使用流程3. 使…

企业级低代码解决方案:JNPF平台深度解析

随着数字化转型的不断推进&#xff0c;企业对于快速开发、高效部署和灵活迭代的需求日益增长。低代码开发平台应运而生&#xff0c;成为加速企业应用开发的重要工具。在众多低代码平台中&#xff0c;JNPF凭借其强大的企业级特性脱颖而出&#xff0c;成为众多企业的首选。本文将…

【系统架构设计师-2019年】综合知识-答案及详解

文章目录 【第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~28题】【第29~30题】【第31~32题】【第33题】【第34题】【第…

Java中三大容器类(List、Set、Map)详解

三大容器介绍 名称结构特点常见实现类List&#xff08;列表&#xff09;由有序的元素序列组成&#xff0c;可以包含重复元素可以通过索引访问元素&#xff0c;插入的顺序与遍历顺序一致ArrayList、LinkedList、VectorMap&#xff08;映射&#xff09;由键值对(Key-Value)组成的…

Axure 9 使用

一、界面初识 二、基础功能 1.菜单栏 1.1文件 新建文件&#xff1a;axure9包含四种文件.rp代表原型文件&#xff0c;.rplib代表元件库文件&#xff0c;.rpteam 团队项目文件 .html 网页文件 偏好设置&#xff1a;备份&#xff0c;需要备份文件再从备份中恢复 创建项目团…

GPT-SoVITS:零样本语音合成AI

GPT-SoVITS 是一种语音合成模型&#xff0c;于 2024 年 2 月 18 日发布。它支持使用参考音频进行零样本语音合成&#xff0c;并且可以进行微调以提高性能。 GPT-SoVITS 的功能特性包括&#xff1a; Zero-Shot TTS&#xff1a;零样本语音合成&#xff0c;输入 5 秒音频样本即可…

57.基于IIC协议的EEPROM驱动控制(4)

&#xff08;1&#xff09;顶层代码&#xff1a; module IIC_EEPROM(input wire clk ,input wire reset_n ,input wire key_r ,input wire key_w ,output wire …

DM一主一实时备一异步备守护集群安装

在前面章节中已经部署了一主一实时备机&#xff0c;此次实施过程中主要添加异步备库。 1. 环境描述 实例详情&#xff1a; 端口详情 2. 关闭主备库守护进程、监视器、数据库实例 [dmdbaray1 ]$ DmWatcherServiceDW stop Stopping DmWatcherServiceDW: …

基于ssm+vue+uniapp的图书管理系统小程序

开发语言&#xff1a;Java框架&#xff1a;ssmuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;M…

JVM 内存参数

文章目录 引言I JVM基础知识Java 语言是解释型的OpenJDK和Sun/Oracle JDK和hotspot的关系JDK、JRE、JVM 之间的关系JVM基础功能JVM组成JIT:Just In Time CompilerJVM内存区域JVM运行时数据区JVM 堆内存布局II JVM 内存参数常用参数JIT编译参数GC信息打印GC参数III 例子引言 J…

M2BEV

Part 1: 2D 图像编码器 给定 NNN 张大小为 HW3的图像&#xff0c;我们对所有图像使用共享的 CNN 主干网络进行前向传播&#xff0c;例如使用 ResNet&#xff0c;并通过特征金字塔网络&#xff08;FPN&#xff09;创建四级特征 F1,F2,F3,F4。 然后&#xff0c;将这些特征全部上…

Quartus网盘资源下载与安装 附图文安装教程

如大家所了解的&#xff0c;Quartus是一种FPGA设计软件&#xff08;相信理工科的小伙伴&#xff0c;很多都接触或学习过FPGA&#xff09;&#xff0c;旨在为数字电路设计师提供一个高效、便捷的开发环境。它可以帮助用户完成数字逻辑电路的设计、仿真、综合和布局&#xff0c;以…

webpack4手动搭建Vue项目

小满视频 很多解释使用通义灵码搜的,通义灵码的搜索结果也是有错误的全程使用pnpm包管理工具&#xff0c;和npm的用法基本一样 学习总结 1. 多看看webpack官网 2. webpack的作用&#xff1a;配置一堆东西&#xff0c;达到运行程序的目的 3. 无论什么东西都转成js&#xff0c;…

什么是CSRF跨站请求伪造

CSRF&#xff08;跨站请求伪造&#xff0c;Cross-Site Request Forgery&#xff09;是一种网络攻击&#xff0c;攻击者通过伪造用户的身份&#xff0c;诱使用户在已认证的 Web 应用上执行非预期的操作。CSRF 攻击的风险在于它能够利用用户的身份认证状态&#xff0c;从而执行恶…

app逆向1-实战里常见东西

幕布链接&#xff1a;app逆向1-实战里常见东西 - 幕布

JVM性能监控实用工具jconsole与jvisualvm

jdk小工具jconsole与jvisualvm&#xff0c;jvisualvm为升级版的jconsole&#xff1b;通过命令行启动&#xff0c;可监控本地和远程应用。 推荐使用&#xff1a;jvisualvm jconsole使用 1.直接命令 jcondole 打开窗口&#xff0c;选择我们要查看的进行 连接后可看到面板 jvisu…

4岁患儿玩耍误伤眼内起迷“障”,耽误多年成都爱尔公益救助手术焕清晰

近日&#xff0c;成都爱尔眼科医院收治了一名来自西藏的7岁小患者小多。小多是由父亲带到医院的&#xff0c;可惜两人都不会汉语&#xff0c;医护人员与他们的交流依靠着孩子父亲拨打的亲戚电话&#xff0c;在电话中一句一句的翻译终于厘清病情原委。 据说&#xff0c;3年前小多…

固态硬盘损坏,有什么方法可以恢复数据?

我认为值得推荐的固态硬盘数据恢复&#xff0c;必须满足2个硬条件&#xff1a; 恢复成功率高 不损害原文件&#xff0c;保证数据的绝对安全 推荐2个超好用的U盘数据恢复神器&#xff0c;帮你快速找回重要文件&#xff01; 1、转转数据恢复大师 点击直达链接>>www.huifuz…

简单工作流-节点增加输入内容

之前已经做完了前端的流程图像绘制&#xff0c;后端对流程图像的CURD&#xff0c;现在主要做流程节点的必要属性做完善&#xff0c;之前只做了节点上权限用户的绑定没有对用户输入内容做管理&#xff0c;现在加上了输入内容管理&#xff0c;具体代码在github上&#xff1a; 前端…

css-50 Projects in 50 Days(1)

改变背景图 html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>改变背景</title><link …