C++11【下】

news2024/10/5 19:15:53

在这里插入图片描述

欢迎来到Cefler的博客😁
🕌博客主页:那个传说中的man的主页
🏠个人专栏:题目解析
🌎推荐文章:题目大解析(3)

在这里插入图片描述


目录

  • 👉🏻 新的类功能
    • 类成员变量初始化
    • 强制生成默认函数的关键字default
    • 禁止生成默认函数的关键字delete
    • 继承和多态中的final与override关键字
  • 👉🏻可变参数模板
    • empalce相关接口函数
  • 👉🏻Lambda表达式
    • 注意要点
    • 函数对象与lambda表达式
  • 👉🏻包装器
    • function包装器
    • function包装器与map的配合使用
  • 👉🏻bind函数
    • 绑定函数指针和参数
    • 绑定函数对象和参数
    • 绑定成员函数和对象指针
    • 绑定函数对象和引用参数

👉🏻 新的类功能

原来C++类中,有6个默认成员函数:

  1. 构造函数
  2. 析构函数
  3. 拷贝构造函数
  4. 拷贝赋值重载
  5. 取地址重载
  6. const 取地址重载
    默认成员函数就是我们不写编译器会生成一个默认的。

C++11 新增了两个:移动构造函数移动赋值运算符重载

🗣 针对移动构造函数和移动赋值运算符重载有一些需要注意的点如下

  • 如果你没有自己实现移动构造函数,且没有实现析构函数拷贝构造拷贝赋值重载中的任
    意一个,即四没。那么编译器会自动生成一个默认移动构造默认生成的移动构造函数,对于内置类
    型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动构造,
    如果实现了就调用移动构造,没有实现就调用拷贝构造
  • 如果你没有自己实现移动赋值重载函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中
    的任意一个,那么编译器会自动生成一个默认移动赋值。默认生成的移动构造函数,对于内
    置类型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动赋
    值,如果实现了就调用移动赋值,没有实现就调用拷贝赋值。(默认移动赋值跟上面移动构造
    完全类似)
  • 如果你提供了移动构造或者移动赋值,编译器不会自动提供拷贝构造和拷贝赋值,如果需要,要自己写了老弟。

类成员变量初始化

C++11允许在类定义时给成员变量初始缺省值,默认生成构造函数会使用这些缺省值初始化

强制生成默认函数的关键字default

C++11可以让你更好的控制要使用的默认函数。假设你要使用某个默认的函数,但是因为一些原
因这个函数没有默认生成。比如:我们提供了拷贝构造,就不会生成移动构造了,那么我们可以
使用default关键字显示指定移动构造生成。

class Person
{
public:
 Person(const char* name = "", int age = 0)
 :_name(name)
 , _age(age)
 {}
 Person(const Person& p)
 :_name(p._name)
 ,_age(p._age)
 {}
 Person(Person&& p) = default;
private:
 bit::string _name;
 int _age;
};
int main()
{
 Person s1;
 Person s2 = s1;
 Person s3 = std::move(s1);
 return 0;
}

禁止生成默认函数的关键字delete

如果能想要限制某些默认函数的生成,在C++98中,是该函数设置成private,并且只声明补丁
已,这样只要其他人想要调用就会报错。在C++11中更简单,只需在该函数声明加上=delete即
可,该语法指示编译器不生成对应函数的默认版本,称=delete修饰的函数为删除函数。

class Person
{
public:
 Person(const char* name = "", int age = 0)
 :_name(name)
 , _age(age)
 {}
 Person(const Person& p) = delete;
private:
 bit::string _name;
 int _age;
};
int main()
{
 Person s1;
 Person s2 = s1;
 Person s3 = std::move(s1);
 return 0;
}

继承和多态中的final与override关键字

这个在【C++】多态中,不再赘述

👉🏻可变参数模板

C++11引入了可变参数模板,它允许函数或类模板接受可变数量的参数。使用可变参数模板可以编写更加灵活和通用的代码。

下面就是一个基本可变参数的函数模板

// Args是一个模板参数包,args是一个函数形参参数包
// 声明一个参数包Args...args,这个参数包中可以包含0到任意个模板参数。
template <class ...Args>
void ShowList(Args... args)
{}

上面的参数args前面有省略号,所以它就是一个可变模版参数,我们把带省略号的参数称为“参数
包”,它里面包含了0到N(N>=0)个模版参数。我们无法直接获取参数包args中的每个参数的,
只能通过展开参数包的方式来获取参数包中的每个参数,这是使用可变模版参数的一个主要特
点,也是最大的难点,即如何展开可变模版参数。由于语法不支持使用args[i]这样方式获取可变
参数,所以我们的用一些奇招来一一获取参数包的值

下面是一个示例,展示了用递归函数方式展开参数包进行使用可变参数模板

#include <iostream>

// 基本情况,递归终止条件
void print() {
    std::cout << std::endl;
}

// 可变参数模板,递归调用打印每个参数
template<typename T, typename... Args>
void print(const T& first, const Args&... args) {
    std::cout << first << " ";
    print(args...);  // 递归调用,传递剩余参数
}

int main() {
    print(1, 2, 3, "hello", 4.5);
    return 0;
}

在上面的示例中,我们定义了一个可变参数模板函数print,它可以接受任意数量的参数。基本情况是一个空函数print(),当没有参数时输出一个换行符。递归情况使用模板参数包(typename... Args)来接受可变数量的参数,并使用递归调用打印每个参数。在main函数中,我们调用print函数,传递了整数、字符串和浮点数作为参数,它们都被打印出来。

使用逗号表达式展开参数包

template <class T>
void PrintArg(T t)
{
 cout << t << " ";
}
//展开函数
template <class ...Args>
void ShowList(Args... args)
{
 int arr[] = { (PrintArg(args), 0)... };
 //int arr[] = { PrintArg(args)...};
 cout << endl;
}
int main()
{
 ShowList(1);
 ShowList(1, 'A');
 ShowList(1, 'A', std::string("sort"));
 return 0;
}

empalce相关接口函数

template <class... Args>
void emplace_back (Args&&... args);

首先我们看到的emplace系列的接口,支持模板的可变参数,并且万能引用。那么相对insert和
emplace系列接口的优势到底在哪里呢?

int main()
{
 std::list< std::pair<int, char> > mylist;
 // emplace_back支持可变参数,拿到构建pair对象的参数后自己去创建对象
 // 那么在这里我们可以看到除了用法上,和push_back没什么太大的区别
 mylist.emplace_back(10, 'a');
 mylist.emplace_back(20, 'b');
 mylist.emplace_back(make_pair(30, 'c'));
 mylist.push_back(make_pair(40, 'd'));
 mylist.push_back({ 50, 'e' });
 for (auto e : mylist)
 cout << e.first << ":" << e.second << endl;
 return 0;
}
int main()
{
// 下面我们试一下带有拷贝构造和移动构造的bit::string,再试试呢
// 我们会发现其实差别也不到,emplace_back是直接构造了,push_back
// 是先构造,再移动构造,其实也还好。
 std::list< std::pair<int, bit::string> > mylist;
 mylist.emplace_back(10, "sort");
 mylist.emplace_back(make_pair(20, "sort"));
 mylist.push_back(make_pair(30, "sort"));
 mylist.push_back({ 40, "sort"});
 return 0;
}

emplace_backpush_back都是向容器中添加元素的成员函数,但它们有一些重要的区别。

push_back函数会创建一个临时对象,并将其复制或移动到容器中。如果容器存储的是对象而不是指针,那么这将涉及到对象的复制或移动构造函数和析构函数的调用。这个额外的开销可能会导致效率降低,特别是在频繁插入元素的情况下。

相比之下,emplace_back函数直接在容器的末尾就地构造一个新的元素(直接构造),而不是先创建一个临时对象。这意味着我们可以避免创建临时对象、复制或移动和析构操作,从而提高性能。实际上,emplace_back通常比push_back更快。

在使用emplace_back时,我们需要注意以下几点:

  1. emplace_back参数应该与容器中元素的构造函数相匹配。

  2. 如果容器存储的是指针,则必须传递指向堆中分配的对象的指针。否则,在容器释放时可能会出现内存泄漏。

  3. 对于std::vectorstd::string等容器,emplace_backpush_back的语义是相同的。

总之,emplace_back是一个更加高效的添加元素的方法,可以避免创建临时对象并提高性能。

👉🏻Lambda表达式

C++11引入了lambda表达式,它是一种方便的方式来创建匿名函数。lambda表达式可以在需要函数对象的地方使用,并且可以捕获周围作用域中的变量。

一个基本的lambda表达式的语法如下:

[capture list](parameters)mutable -> return_type { 
    // 函数体
}

其中:

  • capture list:捕获列表,用于指定lambda表达式访问的外部变量。
  • parameters:参数列表,可选地指定输入参数。
  • return_type:返回类型,可选地指定返回值类型。
  • {}:函数体,包含实际的操作和代码逻辑。
  • mutable:默认情况下,lambda函数总是一个const函数,mutable可以取消其常量性mutable关键字用于在lambda表达式中标记捕获的变量可以被修改。使用该修饰符时,参数列表不可省略(即使参数为空)。

下面是一个简单的示例,展示了lambda表达式的用法:

#include <iostream>

int main() {
    int x = 5;
    int y = 10;

    auto sum = [](int a, int b) -> int {
        return a + b;
    };

    auto result = sum(x, y);
    std::cout << "Sum: " << result << std::endl;

    return 0;
}

在上述示例中,我们定义了一个lambda表达式 sum,它接受两个整数参数并返回它们的和。然后,我们使用该lambda表达式计算变量 xy 的和,并将结果存储在变量 result 中。

lambda表达式还支持捕获外部变量。捕获列表可以指定要在lambda表达式内部使用的外部变量。可以通过值捕获([x])、引用捕获([&x])或混合捕获([x, &y])来捕获变量。

下面是一个使用捕获列表的示例:

#include <iostream>

int main() {
    int x = 5;
    int y = 10;

    auto sum = [x](int a, int b) -> int {
        return a + b + x;
    };

    auto result = sum(y, 15);
    std::cout << "Sum: " << result << std::endl;

    return 0;
}

在上述示例中,我们使用值捕获 [x] 来捕获变量 x,并在lambda表达式内部使用它计算结果。注意,在捕获列表中指定的变量将会被复制到lambda表达式的闭包中。

lambda表达式还可以省略参数列表和返回类型,让编译器自动推断。如果lambda表达式没有参数,则可以使用空括号 () 表示。如果返回类型可以被推断出来,则可以省略返回类型。

除了上述基本用法,lambda表达式还可以与标准库算法(例如std::for_eachstd::transform等)一起使用,以提供更强大的功能。

🍓捕获列表说明

  • [var]:表示值传递方式捕捉变量var
  • [=]:表示值传递方式捕获所有父作用域中的变量(包括this)
  • [&var]:表示引用传递捕捉变量var,传引用不用multable,可以修改
  • [&]:表示引用传递捕捉所有父作用域中的变量(包括this)
  • [this]:表示值传递方式捕捉当前的this指针

注意要点

  • 父作用域指包含lambda函数的语句块

  • 语法上捕捉列表可由多个捕捉项组成,并以逗号分割。
    比如:[=, &a, &b]:以引用传递的方式捕捉变量a和b,值传递方式捕捉其他所有变量
    [&,a, this]:值传递方式捕捉变量a和this,引用方式捕捉其他变量

  • 捕捉列表不允许变量重复传递,否则就会导致编译错误。
    比如:[=, a]:=已经以值传递方式捕捉了所有变量,捕捉a重复

  • 在块作用域以外的lambda函数捕捉列表必须为空。

  • 在块作用域中的lambda函数仅能捕捉父作用域中局部变量,捕捉任何非此作用域或者
    非局部变量都
    会导致编译报错。

  • lambda表达式之间不能相互赋值,即使看起来类型相同

函数对象与lambda表达式

函数对象,又称为仿函数,即可以想函数一样使用的对象,就是在类中重载了operator()运算符的
类对象。

class Rate
{
public:
 Rate(double rate): _rate(rate)
 {}
 double operator()(double money, int year)
 { return money * _rate * year;}
private:
 double _rate;
};
int main()
{
// 函数对象
 double rate = 0.49;
 Rate r1(rate);
 r1(10000, 2);
// lamber
 auto r2 = [=](double monty, int year)->double{return monty*rate*year; 
};
 r2(10000, 2);
 return 0;
 }

从使用方式上来看,函数对象与lambda表达式完全一样。
函数对象将rate作为其成员变量,在定义对象时给出初始值即可,lambda表达式通过捕获列表可
以直接将该变量捕获到。
在这里插入图片描述
实际在底层编译器对于lambda表达式的处理方式,完全就是按照函数对象的方式处理的,即:如
果定义了一个lambda表达式,编译器会自动生成一个类,在该类中重载了operator()。

👉🏻包装器

C++11引入了一系列包装器(Wrappers),用于在编程中提供更多的灵活性和功能。这些包装器是标准库中的模板类,用于封装和操作其他类型的对象。

以下是C++11中的几个常见的包装器:

  1. std::pairstd::pair是一个模板类,用于存储两个不同类型的值。它提供了方便的方式来将两个值组合在一起,并且可以通过firstsecond成员访问其中的值。

  2. std::tuplestd::tuple是一个模板类,用于存储多个不同类型的值。与std::pair类似,std::tuple允许将多个值组合在一起,并且可以使用std::get函数按索引或类型访问其中的值。

  3. std::functionstd::function是一个通用的函数包装器,可以存储可调用对象(如函数、函数指针、lambda表达式等)。它提供了一种机制来传递和存储不同类型的可调用对象,并且可以像普通函数一样进行调用。

  4. std::reference_wrapperstd::reference_wrapper是一个模板类,用于包装对另一个对象的引用。它提供了一种非拥有(non-owning)引用的方式,允许将引用作为值进行传递和存储,而不是像指针一样对对象进行拥有。

这些包装器提供了更高层次的抽象,使得在编程中可以更灵活地处理不同类型的数据和对象。它们有助于提高代码的可读性、可维护性和重用性,并且在许多情况下可以简化编程任务。

function包装器

std::function是一个通用的函数包装器,它可以存储可调用对象(如函数名(函数指针)函数对象lambda表达式类的成员函数等)。使用std::function可以将任何可调用对象视为具有相同签名的函数,并使用相同的方法进行调用。

🍔以下有案例使用

#include <functional>
int f(int a, int b)
{
 return a + b;
}
struct Functor
{
public:
 int operator() (int a, int b)
 {
 return a + b;
 }
};
class Plus
{
public:
 static int plusi(int a, int b)
 {
 return a + b;
 }
 double plusd(double a, double b)
 {
 return a + b;
 }
};
int main()
{
 // 函数名(函数指针)
 std::function<int(int, int)> func1 = f;
 cout << func1(1, 2) << endl;
 // 函数对象
 std::function<int(int, int)> func2 = Functor();
 cout << func2(1, 2) << endl;
 // lamber表达式
 std::function<int(int, int)> func3 = [](const int a, const int b) 
{return a + b; };
 cout << func3(1, 2) << endl;
 
 // 类的成员函数
 std::function<int(int, int)> func4 = &Plus::plusi;
 cout << func4(1, 2) << endl;
 std::function<double(Plus, double, double)> func5 = &Plus::plusd;
 cout << func5(Plus(), 1.1, 2.2) << endl;
 return 0;
}

类的成员函数有点特殊,要&取地址和给出类域。

function包装器与map的配合使用

std::functionstd::map可以很好地配合使用,以实现基于字符串的事件处理程序或回调函数的映射。具体来说,可以将不同的字符串映射到不同的std::function对象上,然后根据字符串查找相应的函数并调用它。

例如,假设需要实现一个简单的命令行工具,用户可以输入不同的命令,然后程序会执行相应的操作。可以使用std::map将不同的命令字符串映射到相应的std::function对象上,然后在用户输入命令时查找相应的函数并调用它。

以下是一个示例代码:

#include <iostream>
#include <map>
#include <functional>

void print_help() {
    std::cout << "Usage: command [args...]\n"
              << "Available commands:\n"
              << "  help - Print this help message\n"
              << "  echo - Print the input arguments\n";
}

void echo(const std::vector<std::string>& args) {
    for (const auto& arg : args) {
        std::cout << arg << " ";
    }
    std::cout << std::endl;
}

int main() {
    std::map<std::string, std::function<void(const std::vector<std::string>&)>> commands{
        {"help", [](const std::vector<std::string>& args){ print_help(); }},
        {"echo", echo}
    };

    std::string command;
    while (true) {
        std::cout << "> ";
        std::getline(std::cin, command);

        std::istringstream iss(command);
        std::string name;
        iss >> name;

        auto it = commands.find(name);
        if (it != commands.end()) {
            std::vector<std::string> args(std::istream_iterator<std::string>{iss},
                                          std::istream_iterator<std::string>{});
            it->second(args);
        }
        else {
            std::cout << "Unknown command: " << name << std::endl;
        }
    }

    return 0;
}

在上面的代码中,我们定义了两个命令函数print_helpecho,分别用于打印帮助信息和输出输入的参数。然后,我们将这两个函数分别存储在std::function对象中,并使用std::map将命令字符串映射到相应的函数上。

main函数中,我们使用一个无限循环来等待用户输入命令。每次输入命令后,我们根据空格拆分输入字符串,并将第一个单词作为命令名称。然后,我们在commands中查找与命令名称匹配的函数,并将剩余的参数传递给它进行处理。

需要注意的是,我们在std::map中使用了std::function对象作为值类型,并指定了函数签名为void(const std::vector<std::string>&),以便与命令处理函数进行匹配。此外,我们还使用了C++11中的初始化列表语法来方便地初始化commands对象。

👉🏻bind函数

std::bind是一个函数,它可以把一个可调用对象和一些参数绑定在一起,返回一个新的可调用对象。这个新的可调用对象可以像原来的可调用对象一样调用,但是其参数已经固定了。

std::bind的语法比较复杂,需要注意以下几点:

  1. 第一个参数是要绑定的可调用对象,可以是函数指针、函数对象、成员函数指针等。
  2. 之后的参数是要绑定的参数,可以是任意类型的值或引用(包括占位符_1_2等)。
  3. 返回值是一个新的可调用对象,其参数个数和类型与原来的可调用对象不同,但可以通过占位符进行传递。

下面是一些常见的用法

绑定函数指针和参数

#include <functional>
#include <iostream>

void foo(int a, int b) {
    std::cout << a << " + " << b << " = " << (a + b) << std::endl;
}

int main() {
    auto f = std::bind(foo, 2, 3);
    f(); // 输出 2 + 3 = 5

    return 0;
}

在上面的代码中,我们使用std::bind将函数foo和参数2、3绑定在一起,生成一个新的可调用对象f。然后,我们调用f()就会执行foo(2, 3)

绑定函数对象和参数

#include <functional>
#include <iostream>

struct Bar {
    void operator()(int a, int b) const {
        std::cout << a << " - " << b << " = " << (a - b) << std::endl;
    }
};

int main() {
    Bar bar;
    auto f = std::bind(bar, 5, std::placeholders::_1);
    f(3); // 输出 5 - 3 = 2

    return 0;
}

在上面的代码中,我们定义了一个函数对象Bar,并重载了其括号运算符。然后,我们使用std::bind将函数对象bar和参数5、占位符_1绑定在一起,生成一个新的可调用对象f。在调用f(3)时,实参3会替换掉占位符_1,最终会执行bar(5, 3)

绑定成员函数和对象指针

#include <functional>
#include <iostream>

struct Baz {
    void hello(int n) const {
        std::cout << "hello " << n << std::endl;
    }
};

int main() {
    Baz baz;
    auto f = std::bind(&Baz::hello, &baz, std::placeholders::_1);
    f(42); // 输出 hello 42

    return 0;
}

在上面的代码中,我们定义了一个类Baz,其中包含一个成员函数hello。然后,我们创建一个Baz对象baz,并使用std::bind将其成员函数hello和对象指针&baz、占位符_1绑定在一起,生成一个新的可调用对象f。在调用f(42)时,实参42会替换掉占位符_1,最终会执行baz.hello(42)

需要注意的是,在绑定成员函数时,需要使用成员函数指针,同时还需要传入一个对象指针作为第一个参数(可以使用&取地址符)。

绑定函数对象和引用参数

#include <functional>
#include <iostream>

struct Foo {
    void operator()(int& n) const {
        n += 10;
    }
};

int main() {
    int x = 5;
    Foo foo;
    auto f = std::bind(foo, std::ref(x));
    f(); // 修改 x 的值为 15
    std::cout << x << std::endl;

    return 0;
}

在上面的代码中,我们定义了一个函数对象Foo,其中包含一个括号运算符,接受一个整数引用,并将其加上10。然后,我们创建一个整数变量x,并使用std::bind将函数对象foo和整数引用x绑定在一起,生成一个新的可调用对象f。在调用f()时,x的值会被修改为15。

需要注意的是,在绑定引用参数时,需要使用std::ref函数将其转换为引用。如果直接绑定一个值,那么修改的只是副本,而不是原来的变量。


如上便是本期的所有内容了,如果喜欢并觉得有帮助的话,希望可以博个点赞+收藏+关注🌹🌹🌹❤️ 🧡 💛,学海无涯苦作舟,愿与君一起共勉成长

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

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

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

相关文章

【pytorch】从yolo的make_grid理解torch.meshgrid、torch.stack

文章目录 简述1、torch.meshgrid 创建行列坐标2、torch.stack 结合行列坐标3、通过view函数扩展维度 简述 yolo检测 make_grid创建网格代码如下&#xff0c;那么什么是torch.meshgrid? def _make_grid(nx20, ny20):yv, xv torch.meshgrid([torch.arange(ny), torch.arange(…

三 STM32F4使用Sys_Tick 实现微秒定时器和延时

更多细节参考这篇 1. 什么是时钟以及作用 1.1 什么是时钟 时钟是由电路产生的周期性的脉冲信号&#xff0c;相当于单片机的心脏 1.2 时钟对于STM32的作用 指令同步&#xff1a;cpu和内核外设使用时钟信号来进行指令同步数据传输控制&#xff1a; 时钟信号控制数据在内部总…

CSS新手入门笔记整理:CSS图片样式

图片大小 语法 width:像素值; height:像素值; 图片边框&#xff1a;border 语法 边框&#xff1a;宽度值 样式值 颜色值&#xff1b; border:1px solid red; 图片对齐 水平对齐&#xff1a;text-align 语法 text-align:取值; 属性值 说明 left 左对齐(默认值) cent…

【Java Web学习笔记】 1 - HTML入门

项目代码 https://github.com/yinhai1114/JavaWeb_LearningCode/tree/main/html 零、网页的组成 HTML是网页内容的载体。内容就是网页制作者放在页面上想要让用户浏览的信息&#xff0c;可以包含文字、图片视频等。 CSS样式是表现。就像网页的外衣。比如&#xff0c;标题字体、…

go学习之goroutine和channel

文章目录 一、goroutine(协程)1.goroutine入门2.goroutine基本介绍-1.进程和线程说明-2.程序、进程和线程的关系示意图-3.Go协程和Go主线程 3.案例说明4.小结5.MPG模式基本介绍6.设置Golang运行的CPU数7.协程并发&#xff08;并行&#xff09;资源竞争的问题8.全局互斥锁解决资…

【渗透】记录阿里云CentOS一次ddos攻击

文章目录 发现防御 发现 防御 流量清洗 使用高防

acwing算法基础之动态规划--数位统计DP、状态压缩DP、树形DP和记忆化搜索

目录 1 基础知识2 模板3 工程化 1 基础知识 暂无。。。 2 模板 暂无。。。 3 工程化 题目1&#xff1a;求a~b中数字0、数字1、…、数字9出现的次数。 思路&#xff1a;先计算1~a中每位数字出现的次数&#xff0c;然后计算1~b-1中每位数字出现的次数&#xff0c;两个相减即…

YOLOv8优化策略:SENetV2,squeeze和excitation全面升级,效果优于SENet | 2023年11月最新成果

🚀🚀🚀本文改进: SENetV2,squeeze和excitation全面升级,作为注意力机制引入到YOLOv8,放入不同网络位置实现涨点 🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK 学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; 1.SENetV2 论文:https://arxiv.org/…

java:springboot3集成swagger(springdoc-openapi-starter-webmvc-ui)

背景 网上集成 swagger 很多都是 Springfox 那个版本的&#xff0c;但是那个版本已经不更新了&#xff0c;springboot3 集成会报错 Typejavax.servlet.http.HttpServletRequest not present&#xff0c;我尝试了很多才知道现在用 Springdoc 了&#xff0c;今天我们来入门一下 …

2023-12-02 LeetCode每日一题(拼车)

2023-12-02每日一题 一、题目编号 1094. 拼车二、题目链接 点击跳转到题目位置 三、题目描述 车上最初有 capacity 个空座位。车 只能 向一个方向行驶&#xff08;也就是说&#xff0c;不允许掉头或改变方向&#xff09; 给定整数 capacity 和一个数组 trips , trip[i] …

国际语音群呼系统

随着海外电话营销的发展&#xff0c;越来越多的出海企业通过国际语音群呼系统打开出海营销之路。企业出海营销运营&#xff0c;选择一个安全、高效、便捷的国际语音群呼系统非常重要。 一、什么是国际语音群呼系统&#xff1f; 国际语音群呼是指通过语音的方式批量向海外用户传…

一进三出宿舍限电模块的改造升级

一进三出宿舍限电模块改造升级石家庄光大远通电气有限公司智能模块功能特点&#xff1a; 电能控制功能&#xff1a;可实施剩余电量管理&#xff0c;电量用完时将自动断电&#xff1b; 剩余电量可视报警提示功能&#xff1a;剩余电量可视&#xff0c;并当电量剩余5度时&#xff…

cpu版本的torch可以用清华镜像源安装

一、来到pytroch官网找到如下代码 官方提供的默认的安装cpu版本的torch的命令 pip3 install torch torchvision torchaudio二、使用清华镜像安装 pip3 install torch torchvision torchaudio -i https://pypi.tuna.tsinghua.edu.cn/simple

力扣题:字符串的反转-11.24

力扣题-11.24 [力扣刷题攻略] Re&#xff1a;从零开始的力扣刷题生活 力扣题1&#xff1a;151. 翻转字符串里的单词 解题思想&#xff1a;保存字符串中的单词即可 class Solution(object):def reverseWords(self, s):""":type s: str:rtype: str"&quo…

项目实战-编写ssm整合配置文件

1、父工程pom.xml <properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><spring.version>…

继承 和 多肽(超重点 ! ! !)

[本节目标] 1.继承 2.组合 3.多肽 1.继承 1.1 为什么要继承 Java中使用类对现实世界中实体来进行描述&#xff0c;类经过实例化之后的产物对象&#xff0c;则可以用来表示现实中的实体&#xff0c;但是现实世界错综复杂&#xff0c;事物之间可能会存在一些关联&#xff0…

计算机组成学习-计算机系统概述总结

1、计算机系统概述 日常见到的计算机有显示器、键盘、鼠标、音箱、主机箱等&#xff1b;主机箱中有&#xff1a;主板、CPU、硬盘、内存、显卡、声卡等&#xff1b; 1.1 计算机系统层次结构 1.2 计算机系统的基本组成 包括硬件系统和软件系统两部分。 1.2.1 计算机硬件 计算…

HarmonyOS 开发案例分享:万能卡片也能用来玩游戏

一、前言 作为一名开发爱好者&#xff0c;从大了讲&#xff0c;我学习并进行 HarmonyOS 相关开发是为了能为鸿蒙生态建设尽一份绵薄之力&#xff0c;从小了讲&#xff0c;就是为了自己的兴趣。而万能卡片是一个让我非常感兴趣的东西。 很多时候我跟别人解释什么是万能卡片&…

LLM:《第 3 部分》从数学角度评估封闭式LLM的泛化能力

一、说明 在 OpenAI 或 Anthropic 等封闭式大型语言模型 (LLM) 领域&#xff0c;对智能和多功能性的真正考验在于它们处理高特异性查询并在响应中表现出独特性的能力。在这篇博客中&#xff0c;我的目标是提供测试这些模型泛化能力的机制。 封闭式LLM意味着您不知道训练语料库的…

matlab操作方法(二)——基本作图

matlab提供很多灵活的二维作图功能函数。这些作图函数分为3类&#xff1a;图形处理、曲线和曲面图的创建、注释和图形特性。作图函数虽多&#xff0c;但语法大致相同 在 MATLAB 中&#xff0c;figure 函数用于创建或选择图形窗口。 matlab figure函数的用法_matlab中figure-C…