【C++】C++11新特性:新的类功能、可变参数模板、STL容器中的empalce相关接口函数、lambda表达式、包装器(function、bind)

目录

一、新的类功能

1.1 移动构造函数和移动赋值运算符重载

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

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

1.4 其它的类功能

二、可变参数模板

三、STL容器中的empalce相关接口函数

四、lambda表达式

4.1 lambda的引入

4.2 lambda表达式语法

4.2.1 lambda表达式各部分说明

4.2.2 捕获列表说明

4.3 函数对象与lambda表达式

五、包装器

5.1 function包装器

5.2 bind包装器


一、新的类功能

1.1 移动构造函数和移动赋值运算符重载

在以前的C++时,我们知道C++的类有6个默认成员函数:
1. 构造函数
2. 析构函数
3. 拷贝构造函数
4. 拷贝赋值重载
5. 取地址重载
6. const 取地址重载
比较重要的是前4个,后两个用处不大。默认成员函数就是我们不写编译器会生成一个默认的。

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

移动构造函数和移动赋值运算符重载有一些需要注意的点:

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

注:

  • 如果想要使用默认生成的移动构造/移动赋值重载,那么析构函数、拷贝构造、赋值重载都不能自己定义实现。但可以实现构造函数。
  • 一般析构函数、拷贝构造、赋值重载作为一个整体出现。比如一般出现析构函数,就说明类的内部实现了开辟空间请求资源,析构函数是为了释放资源。既然申请了资源,拷贝时就要进行深拷贝,于是就有了拷贝构造和赋值拷贝。

下面的示例中只实现了构造函数,mystring是上一篇中定义的类在此不作赘述。main函数要使用Person默认生成的拷贝构造和移动构造,之前讲过,默认生成的拷贝构造对内置类型浅拷贝,对自定义类型用它自己的拷贝构造(如果它有的话)。

class Person
{
public:Person(const char* name = "", int age = 0):_name(name), _age(age){}private:mystring::string _name;int _age;
};int main()
{Person s1;Person s2 = s1;			   // 默认的拷贝构造Person s3 = std::move(s1); // 默认的移动构造return 0;
}

如果我们定义了析构函数、拷贝构造、赋值重载其中的任意一个,那么移动构造就不会默认生成,比如定义析构函数,就不会生成和使用默认的移动构造,而是使用默认的拷贝构造。

	~Person(){cout << "~Person()" << endl;}

 

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

如果我们既想生成析构函数、拷贝构造、赋值重载其中几个,又想生成默认的移动构造/移动赋值重载。可以使用default关键字强制生成默认的某些函数。

比如:我们提供了拷贝构造,就不会生成移动构造了,那么我们可以
使用default关键字显示指定移动构造生成。(也要强制生成默认的拷贝构造)

	// 强制编译器生成Person(Person&& p) = default;Person(const Person& p) = default;

如果不强制生成默认的拷贝构造函数会报错,因为强制生成移动构造后,就不会生成拷贝构造了。

编译器生成默认的拷贝构造函数和拷贝赋值运算符的条件是:

  • 类中没有定义拷贝构造函数或拷贝赋值运算符。
  • 类中没有定义移动构造函数或移动赋值运算符。
  • 类中没有定义任何构造函数(除了默认构造函数)。

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

在 C++98 中,如果想要阻止编译器生成某个函数的默认版本,可以将该函数声明为私有,并且只声明不实现。这样,除了类内部之外,外部无法访问这个函数,从而阻止了编译器生成默认版本,其他人想要调用就会报错。

在C++11中更简单,只需在该函数声明加上=delete即可,这将告诉编译器不要生成该函数的默认版本,从而防止它被外部调用。称=delete修饰的函数为删除函数。 

Person(Person&& p) = delete;

1.4 其它的类功能

C++_好像有点东西的博客-CSDN博客

1.类成员变量初始化

C++11允许在类定义时给成员变量初始缺省值,默认生成构造函数会使用这些缺省值初始化,这
个我们在类和对象默认就讲了,这里就不再细讲了。

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

这个我们在继承和多态部分已经进行了详细讲解这里就不再细讲。只是强调两点:

final 关键字
用途:final 关键字用于修饰类或者函数,表示不允许被继承或者重写。
类修饰:当 final 修饰一个类时,它表示该类不能被其他类继承。
函数修饰:当 final 修饰一个函数时,它表示该函数不能被派生类重写。

override 关键字
用途:override 关键字用于修饰虚函数,表示该虚函数是在派生类中重写的基类虚函数。
条件:override 修饰的虚函数必须在派生类中有一个基类虚函数与之匹配。
错误:如果 override 修饰的虚函数在派生类中没有重写基类虚函数,或者重写的函数不符合匹配条件,编译器会报错。

二、可变参数模板

C++11的新特性可变参数模板能够让我们创建可以接受可变参数的函数模板和类模板,相比C++98/03,类模版和函数模版中只能含固定数量的模版参数,可变模版参数无疑是一个巨大的改
进。然而由于可变模版参数比较抽象,使用起来需要一定的技巧,所以这块还是比较晦涩的。我们现阶段掌握一些基础的可变参数模板特性就够我们用了。

下面是一个可变参数的函数模板:

  • Args是一个模板参数包,args是一个函数形参参数包
  • 声明一个参数包Args... args,这个参数包中可以包含0到任意个模板参数。
  • sizeof...(args) 来获取参数包中参数的数量
template <class... Args>
void ShowList(Args... args)
{//cout << sizeof(args) << endl;//错误用法//sizeof...(args) 来获取参数包中参数的数量cout << sizeof...(args) << endl;
}int main()
{ShowList(1);ShowList(1, 2, 3);return 0;
}

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

void _ShowList()
{cout << endl;
}// 编译时的递归推演
// 第一个模板参数依次解析获取参数值
template <class T, class ...Args>
void _ShowList(const T& val, Args... args)
{cout << val << " ";_ShowList(args...);
}template <class ...Args>
void ShowList(Args... args)
{_ShowList(args...);
}int main()
{ShowList(1);ShowList(1, 2);ShowList(1, 2, 3);ShowList(1, 2.2, 'x', 3.3);return 0;
}

简单解释过程:

  • 例如ShowList(1, 2, 3);函数把参数1,2,3传给_ShowList,在这个函数参数(const T& val, Args... args)里,1被看作第一个参数val,后面的所有参数2和3看作一个参数包。
  • 打印val,再递归调用_ShowList(val, args)。这个_ShowList函数里参数2被看作第一个参数val,后面的所有参数3看作一个参数包。
  • 打印val,再递归调用_ShowList(val,args)。这个_ShowList函数里参数3被看作第一个参数val,后面没有参数,args参数为空。
  • 打印val,因为args参数为空,递归调用_ShowList()。输出换行。

方法2:

template <class T>
int PrintArg(T&& t)
{cout << t << " ";return 0;
}//展开函数
template <class... Args>
void ShowList(Args&&... args)
{// 要初始化arr,强行让编译器解析参数包,参数包有几个参数,PrintArg就依次推演生成几个int arr[] = { PrintArg(args)... };cout << endl;
}
  • 使用模板参数包推演初始化一个数组 arr,并且让编译器解析参数包,生成与参数包中参数数量相等的 PrintArg 调用。这是通过使用 ... 运算符在数组初始化表达式中实现的。
  • ... 运算符在 C++ 中被称为展开运算符,它用于将模板参数包中的每个参数依次传递给函数或模板。在这个例子中,PrintArg(args)... 表达式会依次调用 PrintArg 函数,每个参数调用一次。
  • 在 ShowList 函数中,使用 { PrintArg(args)... } 表达式来初始化数组 arr。这个表达式会依次调用 PrintArg 函数,每个参数调用一次。由于 PrintArg 函数返回 int 类型,所以数组 arr 中的每个元素都是 int 类型的,但它们的值是 PrintArg 函数的返回值,即 0。

三、STL容器中的empalce相关接口函数

list::emplace_back - C++ Reference (cplusplus.com)

vector::emplace_back - C++ Reference (cplusplus.com)

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

emplace 相关接口函数在 C++ 中提供了一种高效的方式来在容器中插入元素。

int main()
{std::list<mystring::string> lt;mystring::string s1("1111");lt.push_back(s1);lt.push_back(move(s1));cout << endl;mystring::string s2("1111");lt.emplace_back(s2);lt.emplace_back(move(s2));cout << endl;lt.push_back("xxxx");cout << endl;lt.emplace_back("xxxx");return 0;
}

 

empalce_back与push_back的对比:

  • emplace_back 和 push_back 是 C++ 中用于在容器末尾插入元素的两个方法。
  • 它们的效率在插入自定义对象时差不多,都可以使用相应的深拷贝和移动拷贝。
  • 但是在使用变量传参发生隐式类型时,push_back要进行构造加移动拷贝,而emplace_back直接将这个值一步步传给内部的构造函数构造。省略了移动拷贝的过程。
  • 所以emplace_back() 在插入大量元素时比 push_back() 更高效。但实际使用时差距也不是很大。大家可以根据自己情况选择使用。

四、lambda表达式

4.1 lambda的引入

在C++98中,如果想要对一个数据集合中的元素进行排序,可以使用std::sort方法。但是如果待排序元素为自定义类型,需要用户定义排序时的比较规则。例如一个类中有不同的值可以排序,就要写不同的排序方法。如商品的名称、价格、评分。

随着C++语法的发展,人们开始觉得上面的写法太复杂了,每次为了实现一个algorithm算法,都要重新去写一个类,如果每次比较的逻辑不一样,还要去实现多个类,特别是相同类的命名,这些都给编程者带来了极大的不便。因此,在C++11语法中出现了Lambda表达式

4.2 lambda表达式语法

lambda表达式书写格式:
[capture-list] (parameters) mutable -> return-type { statement }

4.2.1 lambda表达式各部分说明

  • [capture-list] : 捕捉列表。该列表总是出现在lambda函数的开始位置,编译器根据[]来判断接下来的代码是否为lambda函数,捕捉列表能够捕捉上下文中的变量供lambda函数使用。
  • (parameters):参数列表。与普通函数的参数列表一致,如果不需要参数传递,则可以连同()一起省略。
  • mutable:取消常量性可以省略。默认情况下,lambda函数总是一个const函数,mutable可以取消其常量性。使用该修饰符时,参数列表不可省略(即使参数为空)。
  • ->returntype:返回值类型。用追踪返回类型形式声明函数的返回值类型,没有返回值时此部分可省略。返回值类型明确情况下,一般可以省略,由编译器对返回类型进行推导。
  • {statement}:函数体。在该函数体内,除了可以使用其参数外,还可以使用所有捕获到的变量。

注意:

  • 在lambda函数定义中,有参数列表、返回值类型还有函数体,与函数的不同就是多加了方括号[]和mutable。
  • lambda可以简单理解为匿名函数对象。该函数无法直接调用,如果想要直接调用,可借助auto将其赋值给一个变量。

4.2.2 捕获列表说明

捕捉列表描述了上下文中那些数据可以被lambda使用,以及使用的方式传值还是传引用。

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

注意:

  • 传值方式捕捉的变量不能被修改,捕捉后就成了类仿函数内部的成员变量,但是这个变量是const修饰的。如果需要修改,就需要在表达式加上mutable。
  • 传值方式捕捉的变量和外部的变量不是同一个,即使内部可以修改,也不会影响外部的变量值。
  • [&var] 不是取地址,而是以引用的方式捕捉对象。不需要再加mutable。想加上也可以加。
  • 父作用域指包含lambda函数的语句块
  • 语法上捕捉列表可由多个捕捉项组成,并以逗号分割。比如:
    [=, &a, &b]:以引用传递的方式捕捉变量a和b,值传递方式捕捉其他所有变量
    [&,a, this]:值传递方式捕捉变量a和this,引用方式捕捉其他变量,捕捉this就可以访问成员变量。
  • 捕捉列表不允许变量重复传递,否则就会导致编译错误。 比如:[=, a]:=已经以值传递方式捕捉了所有变量,捕捉a重复。
  • lambda表达式之间不能相互赋值,即使看起来类型相同

在 C++ 中,当您创建一个 lambda 函数时,您可以选择捕捉外部作用域中的变量。如果您的 lambda 函数在块作用域(如循环、函数或模板参数包)之外定义,那么它不能捕捉任何变量。这被称为“封闭规则”或“封闭性规则”。

具体来说,这意味着:

  • 块作用域:如果 lambda 函数定义在一个块作用域内(如在循环中),它可以捕捉该块作用域内的变量。
  • 函数作用域:如果 lambda 函数定义在一个函数内,它可以捕捉该函数作用域内的变量。
  • 全局作用域:如果 lambda 函数定义在一个全局作用域内,或者在块作用域之外定义,它不能捕捉任何变量。

这主要是因为当 lambda 函数在全局作用域或块作用域之外定义时,它没有明确的“封闭”作用域。如果它捕捉了外部变量,那么这些变量必须被保持不变,以便 lambda 函数在它的生命周期内能够访问它们。然而,这通常是不可能的,因为这些变量可能在 lambda 函数创建后不久就被销毁或更改。

class AA
{
public:void func(){/*auto f1 = [this]() {cout << a1 << endl;cout << a2 << endl;};*///lambda可以在成员函数内部//不可以使用a1,a2,因为捕捉列表是捕捉父作用域的变量,a1a2不是父作用域的变量auto f1 = [a1, a2]() {cout << a1 << endl;cout << a2 << endl;};//捕捉使用this,编译器做了优化处理,不用写this->a1,this->a2auto f1 = [=]() {cout << a1 << endl;cout << a2 << endl;};f1();}
private:int a1 = 1;int a2 = 1;
};

4.3 函数对象与lambda表达式

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

class Rate
{
public:Rate(double rate):_rate(rate){}double operator()(double money, int year){return money * year * _rate;}
private:double _rate;
};int main()
{double rate = 0.13;//使用函数对象Rate r1(rate);int tmp = r1(10000, 2);//使用lambda表达式auto r2 = [=](double money, int year) {return money * year * rate;};int tmp2 = r2(10000, 2);return 0;
}

从使用方式上来看,函数对象与lambda表达式完全一样。

函数对象将rate作为其成员变量,在定义对象时给出初始值即可,lambda表达式通过捕获列表可
以直接将该变量捕获到。

实际在底层编译器对于lambda表达式的处理方式,完全就是按照函数对象的方式处理的。
即:如果定义了一个lambda表达式,编译器会自动生成一个类,在该类中重载了operator()。

名字是<lambda_uuid>,即lambda+uuid,随机生成 。

五、包装器

5.1 function包装器

function包装器 也叫作适配器。C++中的function本质是一个类模板,也是一个包装器。

包装器包装的是可调用对象:函数指针、函数对象、仿函数、lambda表达式。

为什么要引入function包装器?

之前学习的函数指针、仿函数、lambda表达式在使用时都有各自的缺点,例如:

  • 函数指针的缺点:类型不好写。(void (*funcName)(int x, int y);)
  • 仿函数的缺点:类型好写,但是每次使用都需要写一个类,比较笨重.
  • lambda缺点:简洁,但是不好描述类型。不同机器的UUID不同,类型结果不同,即类型是相对匿名的。decltype可以获得类型。

function包装器的表达式语法:

std::function在头文件<functional>
// 类模板原型如下
template <class T> function;     // undefined


template <class Ret, class... Args>
        class function<Ret(Args...)>;

模板参数说明:
Ret: 被调用函数的返回类型
Args…:被调用函数的形参

void swap_func(int& r1, int& r2)
{int tmp = r1;r1 = r2;r2 = tmp;
}class Swap
{
public:void operator()(int& r1, int& r2){int tmp = r1;r1 = r2;r2 = tmp;}
};int main()
{int x = 1, y = 2;cout << x << "  " << y << endl;auto swap_lambda = [](int& r1, int& r2) {int tmp = r1;r1 = r2;r2 = tmp;};function<void(int&, int&)> f1 = swap_func;f1(x, y);cout << x << "  " << y << endl;function<void(int&, int&)> f2 = Swap();f2(x, y);cout << x << "  " << y << endl;function<void(int&, int&)> f3 = swap_lambda;f3(x, y);cout << x << "  " << y << endl;map<string, function<void(int&, int&)>> Option ={{"函数指针", swap_func},{"仿函数", Swap()},{"lambda表达式",swap_lambda}};Option["函数指针"](x, y);cout << x << "  " << y << endl;Option["仿函数"](x, y);cout << x << "  " << y << endl;Option["lambda表达式"](x, y);cout << x << "  " << y << endl;return 0;
}

如果function包装的是类的成员对象,

  1. 需要在对象前面加上类域和& ,&用来取地址,因为普通函数的函数名就是地址,静态的成员函数可以不加,但是推荐加上。
  2. 包装非静态成员函数,需要在Args…(被调用函数的形参)中指定类的实例化对象的地址。因为非静态成员函数的参数还有一个隐含的this指针。
  3. 编译器进行优化,可以在Args中实例化匿名对象,不用再实例化出对象传址。
class Plus
{
public:static int plusi(int a, int b){return a + b;}double plusd(double a, double b){return a + b;}
};int main()
{// 成员函数取地址,比较特殊,要加一个类域和&function<int(int, int)> f1 = &Plus::plusi;cout << f1(1, 2) << endl;//function<double(double, double)> f2 = &Plus::plusd;//会报错,因为非静态成员函数的参数还有一个隐含的this指针。function<double(Plus*, double, double)> f2 = &Plus::plusd;Plus ps;cout << f2(&ps, 1.1, 2.2) << endl;//编译器进行优化,不用再实例化出对象传址function<double(Plus, double, double)> f3 = &Plus::plusd;cout << f3(Plus(), 1.1, 2.2) << endl;return 0;
}

5.2 bind包装器

function处理类的成员函数时,每次都要在参数上加上类名或者类的指针。为了减少操作,引入了bind,用来调节可调用对象的参数列表。

std::bind 是头文件functional的一个函数模板,它就像一个函数包装器(适配器),接受一个可调用对象和可选的参数绑定列表,生成一个新的可调用对象来“适应”原对象的参数列表。这个新的可调用对象可以被用来调用原始的可调用对象,并且可以改变参数的顺序或绑定一些参数的值。

原型如下:

bind的主要作用:

  1. 调整参数顺序
  2. 调整参数个数,有些参数可以绑定(bind)时写死。

调用bind的一般形式:auto newCallable = bind(callable,arg_list);
其中,newCallable本身是一个可调用对象,arg_list是一个逗号分隔的参数列表,对应给定的可调用对象callable的参数。当我们调用newCallable时,newCallable会调用callable,并传给它arg_list中的参数。
arg_list中的参数可能包含形如_n的名字,其中n是一个整数,这些参数是占位符(placeholders),表示newCallable的参数,它们占据了传递给newCallable的参数的“位置”。数值n表示生成的可调用对象中参数的位置:_1为newCallable的第一个参数,_2为第二个参数,以此类推。

int Sub(int a, int b)
{return a - b;
}int main()
{function<int(int, int)> f1 = Sub;cout << f1(10, 5) << endl;// 调整参数顺序function<int(int, int)> f2 = bind(Sub, placeholders::_2, placeholders::_1);cout << f2(10, 5) << endl;// 调整参数个数,有些参数可以绑定(bind)时写死function<int(int)> f3 = bind(Sub, 20, placeholders::_1);cout << f3(5) << endl;return 0;
}
    function<double(double, double)> f4 = bind(&Plus::plusd, Plus(), placeholders::_1, placeholders::_2);cout << f4(1.11, 2.22) << endl;

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

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

相关文章

openVPN+SmartDNS=openDNS or smartVPN?

正文共&#xff1a;777 字 11 图&#xff0c;预估阅读时间&#xff1a;1 分钟 我们现在已经熟练的掌握了openVPN的部署方式和配置方法&#xff08;带认证的openVPN连接/断开操作指南&#xff09;&#xff0c;还掌握了在CentOS系统部署SmartDNS的方法&#xff08;基于CentOS部署…

【网络安全】Web安全基础 - 第二节:前置基础知识- HTTP协议,握手协议,Cookie及Session

本章节主要介绍一些基础知识 d(^_^o) HTTP协议 什么是HTTP 超文本传输协议&#xff08;HyperText Transfer Protocol&#xff09;是一种用于分布式、协作式和超媒体信息系统的应用层协议。 HTTP是一个基于请求与响应&#xff0c;无状态的&#xff0c;应用层协议&#xff0c;…

100.网络游戏逆向分析与漏洞攻防-ui界面的设计-聊天功能的界面与设计

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 如果看不懂、不知道现在做的什么&#xff0c;那就跟着做完看效果 现在的代码都是依据数据包来写的&#xff0c;如果看不懂代码&#xff0c;就说明没看懂数据包…

Git常用命令1

1、设置用户签名 ①基本语法&#xff1a; git config --global user.name 用户名 git config --global user.email 邮箱 ②实际操作 ③查询是否设置成功 cat ~/.gitconfig 注&#xff1a;签名的作用是区分不同操作者身份。用户的签名信息在每一个版本的提交…

MulterError: Field name missing 报错解决

Request POST /FileUpload/chunkApi/upload/mProjectNews/Images failed with status code 500. MulterError: Field name missing. 原因&#xff1a;Multer是基于Busboy解析的表单参数信息&#xff0c;经定位发现是解析表单中文本参数时出现了null&#xff0c;故收到MISSION_…

【算法】模拟算法——数青蛙(medium)

题解&#xff1a;模拟算法——数青蛙(medium) 目录 1.题目2.题解3.参考代码4.总结 1.题目 题目链接&#xff1a;LINK 2.题解 用循环进行遍历&#xff0c; 如果该字符为o\o\a\k 找一下前驱字符是否存在 如果存在&#xff0c;前驱字符–&#xff0c;该字符如果不存在&#x…

CATIA二次开发VBA入门(4)——进程外开发环境搭建,vb.net在Visual Studio中开发,创建圆柱曲面的宏录制到二次开发案例

目录 引出vb.net和vb6.0 进程外开发环境搭建vb.net开发环境搭建《CATIA二次开发技术基础》模板 添加宏库引用 vs开发环境初步vs中的立即窗口对象浏览器 建立模板案例&#xff1a;创建一堆圆柱曲面第一步&#xff1a;录制宏第二步&#xff1a;代码精简第三步&#xff1a;for循环…

⌈ 传知代码 ⌋ 命名实体识别

&#x1f49b;前情提要&#x1f49b; 本文是传知代码平台中的相关前沿知识与技术的分享~ 接下来我们即将进入一个全新的空间&#xff0c;对技术有一个全新的视角~ 本文所涉及所有资源均在传知代码平台可获取 以下的内容一定会让你对AI 赋能时代有一个颠覆性的认识哦&#x…

提升B端图表设计技能:教程分享

图表是数据可视化的常用表现形式&#xff0c;是对数据的二次加工&#xff0c;可以帮助我们理解数据、洞悉数据背后的真相&#xff0c;让我们更好地适应这个数据驱动的世界。本期就来带大家学习图表的设计及构成&#xff0c;帮助大家更好的理解图表设计。 设计教程源文件http:/…

OpenAI已全面开放自定义GPT以及文件上传等功能

今天&#xff0c;OpenAI兑现了前段时间做出的承诺&#xff1a;免费向所有用户开放GPT-4o。这意味着所有的免费用户都能使用自定义GPT模型、分析图表等其他GPT-4o新功能了。现在ChatGPT界面长这样&#xff1a; 可以看出&#xff0c;免费用户也能使用GPT store中定义好的模型&…

Python开发与应用实验1 | 开发环境安装配置

*本文来自博主对专业课 Python开发与应用 实验部分的整理与解析。 *一些题目可能会增加了拓展部分&#xff08;⭐&#xff09;。拓展部分不是实验报告中原有的内容&#xff0c;而是博主本人的补充&#xff0c;以便各位学习参考。 *实验环境为&#xff1a;Python 3.10 &#xf…

java实现地形dem产汇流流场数据提取解析

一、基础概念 在GIS和气象学、海洋学、大气科学、水文学等领域&#xff0c;"提取流场"通常指的是从数据集中识别和分析流体&#xff08;如水流、风场、洋流、大气流&#xff09;的运动模式和流向的过程。这个过程涉及数据处理、可视化和分析技术&#xff0c;下面是提…

Wpf 使用 Prism 实战开发Day31

登录数据绑定 1.首先在LoginViewModel 登录逻辑处理类中&#xff0c;创建登录要绑定属性和命令 public class LoginViewModel : BindableBase, IDialogAware {public LoginViewModel(){ExecuteCommand new DelegateCommand<string>(Execure);}public string Title { ge…

vue-标签选择

效果 选中后 代码 <span :class"[item.bealtrue?p_yx_span span_active :span p_yx]" click"onTagSelect(index)" v-for"(item,index) in tagList" :key"index" >{{item.name}} </span> // 列表值 tagList:[ {id: 1, na…

R语言ggplot2包绘制世界地图

数据和代码获取&#xff1a;请查看主页个人信息&#xff01;&#xff01;&#xff01; 1. 数据读取与处理 首先&#xff0c;从CSV文件中读取数据&#xff0c;并计算各国每日收入的平均签证成本。 library(tidyverse) ​ df <- read_csv("df.csv") %>% group_…

PostgreSQL基础(六):PostgreSQL基本操作(二)

文章目录 PostgreSQL基本操作(二) 一、字符串类型 二、日期类型 三、

基于分步傅立叶数值算法的一维非线性薛定谔方程求解matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于分步傅立叶数值算法的一维非线性薛定谔方程求解matlab仿真. 2.测试软件版本以及运行结果展示 MATLAB2022A版本运行 3.核心程序 ........................…

今天,组长和研发总监吵起来了 ...

插&#xff1a; AI时代&#xff0c;程序员或多或少要了解些人工智能&#xff0c;前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家(前言 – 人工智能教程 ) 坚持不懈&#xff0c;越努力越幸运&#xff0c;大家…

下载HF AutoTrain 模型的配置文件

下载HF AutoTrain 模型的配置文件 一.在huggingface上创建AutoTrain项目二.通过HF用户名和autotrain项目名,拼接以下url,下载模型列表(json格式)到指定目录三.解析上面的json文件、去重、批量下载模型配置文件(权重以外的文件) 一.在huggingface上创建AutoTrain项目 二.通过HF用…

Flutter中如何让Android的手势导航栏完全透明?

Flutter 开发中 安卓机器都有 像ios 的手势操作栏&#xff0c; 也就是屏幕底下的 那条线。 但这条线默认是有颜色的 &#xff08;像下面这样&#xff09; 一、全屏幕方式 void main() {// 全屏沉浸式SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []…