C++11特性详解

一、简介

在C++11标准出来之前,一直是C++98/03标准占引领地位,而C++98/03标准是C++98标准在2003年将存在的一些漏洞进行了修复,但并没有核心语法的改动。相比于C++98/03,C++11则带来了数量可观的变化,其中包含了约140个新特性,以及对C++03标准中约600个缺陷的修正,这使得C++11更像是从C++98/03中孕育出的一种新语言。相比较而言,C++11能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅功能更强大,而且能更好的提升开发效率。本文主要对一些常用的新特性进行讲解。

二、列表初始化 {}

2.1 C++98中的{}

C++98标准中,允许使用{}对数组或结构体元素进行统一的列表初始化:

struct Test
{
	int _x;
	int _y;
};
int main()
{
	int array1[] = { 1, 2, 3, 4, 5 };  // 数组列表初始化
	int array2[5] = { 0 };  // 数组列表初始化
	Test t = { 1, 2 };  // 结构体列表初始化
	return 0;
}

2.2 C++11中的{} 

在新出的C++11标准中,扩大了{}的使用范围,可以对所有的内置类型和用户自定义的类型使用初始化列表{},可以使用或不使用等号(=)

struct Test
{
	int _x;
	int _y;
};
int main()
{
	int array1[5] = { 1, 2, 3, 4, 5 };  //使用等号
	int array2[5]{ 1, 2, 3, 4, 5 };  //不使用等号

	int x = 1;
	int y{ 1 };  // 这种初始化不使用等号,看着感觉怪怪的,所以还是建议使用等号进行初始化
	
	Test t1 = { 1, 2 };  //使用=
	Test t2{ 1,2 };  // 不使用=

    //STL容器的使用
    vector<int> v{1,2,3,4,5};
    map<int, int> m{{1,1}, {2,2,},{3,3},{4,4}};
	return 0;
}

 对于自定义类型的列表初始化:

class Date
{
public:
	Date(int year, int month, int day)
		:_year(year)
		, _month(month)
		, _day(day)
	{
		cout << _year<<"-"<<_month<<"-"<<_day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1(2022, 1, 1); // 原始的初始化方法
	// 使用C++11支持的列表初始化,这里会调用构造函数初始化
	Date d2{ 2022, 1, 2 };
	Date d3 = { 2022, 1, 3 };
	return 0;
}

 2.3 std::initializer_list

官方文档,点击查看

 为什么C++11会支持新的{}的列表初始化呢?

因为以上的所有类型都支持了以std::initializer_list作为参数的构造函数。

比如list,vector, map等:

 

 

 三、声明

3.1 auto

在之前的C++98标准中,auto是一个存储类型的说明符,表明变量是局部自动存储类型,但是局部域中定义局部的变量默认就是自动存储类型,使得auto没有任何的价值体现,所以,在C++11中就废除了原先的auto用法,定义了一个全新的auto。C++11中,将其用于实现自动类型的推导,要求必须进行显示初始化,让编译器将定义对象的类型设置为初始化值的类型。使用auto,能使程序的书写提供便利及整体代码的简洁性。

	int i = 10;
	auto p = &i;  // 推导出p的类型应该为int*
	auto pf = "string";  // pf:  char const*
	cout << typeid(p).name() << endl;
	cout << typeid(pf).name() << endl;
	map<string, string> dict = { {"sort", "排序"}, {"insert", "插入"} };

	//使用auto自行推导出迭代器的类型,使代码简洁
	map<string, string>::iterator it1 = dict.begin();  
	auto it2 = dict.begin();

 3.2 decltype 

auto进行类型推导时必须进行显示初始化,否则auto是无法进行推导,编译器编译不过。而关键字decltype则将变量的类型声明为表达式指定的类型。如下使用:

	const int x = 2;
	double y = 3.3;
	decltype(x * y) ret;  // 推出ret的类型是double
	decltype(&x) p;  // 推出p的类型是int *
	cout << typeid(ret).name() << endl;
	cout << typeid(p).name() << endl;

3.3 nullptr

// C++中NULL的定义
#ifndef NULL
    #ifdef __cplusplus
        #define NULL 0
    #else
        #define NULL ((void *)0)
    #endif
#endif


// C++中nullptr的定义
#if defined(nullptr)
#define nullptr EMIT WARNING C4005
#error The C++ Standard Library forbids macroizing the keyword "nullptr". \
Enable warning C4005 to find the forbidden define.
#endif // nullptr

在C++中,NULL被定义成字面量0,在使用的过程中可能会带来一些问题,因为0既能表示指针常量,又能表示整形常量。所以出于清晰和安全的角度考虑,C++11中新增了nullptr,用于表示空指针,使用nullptr更为安全。

四、final 与 override

final的作用:

a. C++11中,将类标记为final后,该类会禁止被继承。

b. 用final修饰虚函数是,该虚函数将不可被重写。

override的作用(用于派生类函数):
a. override用于在派生类中显式地重写基类中的虚函数。

b.  它可以确保在派生类中正确地覆盖基类的虚函数,并且如果没有正确地重写,则会产生编译错误。

五、=default 和 =delete

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

class A
{
public:
	A() = default;  //让编译器默认生成无参构造函数
	A(int num)    // 存在有参构造,编译器不会默认生成无参构造,所有需要用default让编译器生成一下
		:_num(num)
	{}
	void fun()
	{
		cout << "A::func()" << endl;
	}
private:
	int _num;
};

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

class A
{
public:
	A(int a) : _a(a){}
	//C++11
	A(const A&) = delete;  //禁止编译器生成默认的拷贝构造函数
	A& operator=(const A&) = delete;  //禁止编译器生成赋值运算符重载
private: 
	int _a;
	//C++98,设置成private
	A(const A&) = delete;
	A& operator=(const A&) = delete;
};

 六、可变参数模板

 介绍

可变参数模板是指可以定义0到任意个模板参数的模板,它可以用来实现高度泛化的函数或类。可变参数模板的语法是使用省略号(…)来表示一个或多个参数。比如一个我们很熟悉的函数的参数就是可变参数:printf。它不仅可以接受不同数量的参数,还能接受不同类型的参数。

模板结构:

template<class …Args>
返回类型 函数名(Args… args)
{
    //函数体
}

示例:

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

 作用

  1. 函数参数的数量不确定性: 可变参数模板允许函数接受任意数量的参数,可以在函数体内对这些参数进行处理。这在实现一些工具函数、容器类或者模板库时非常有用,比如 printf 风格的输出函数。

  2. 递归模板展开: 可变参数模板可以通过递归展开,用于在编译时展开模板参数的各个部分。这在实现一些递归算法或数据结构时非常有用,例如元组、可变参数列表的操作等。

  3. 多态参数: 可变参数模板使得可以将不同类型的参数传递给同一个函数或类模板,并在函数内部根据参数的类型来执行不同的操作,从而实现更通用的函数。

  4. 日志记录和调试: 可变参数模板可以用于实现灵活的日志记录和调试函数,能够根据不同的调用情况输出不同的信息。

  5. 类型安全的变参函数: 可变参数模板相对于C语言中的可变参数函数(如 printf)来说,能够提供更好的类型安全性,因为在编译时就可以对参数类型进行检查。

如下例子展示如何使用可变参数模板来实现递归求和:

#include <iostream>

// 递归模板展开,计算可变数量参数的和
template<typename T>
T sum(T value) {
    return value;
}

template<typename T, typename... Args>
T sum(T value, Args... args) {
    return value + sum(args...);
}

int main() {
    int res = sum(1, 2, 3, 4, 5);
    std::cout << "sum: " << res << std::endl; // 输出 15

    return 0;
}

 因为语法不支持使用args[i]这样方式获取可变参数,所以就通过递归的方式将参数包进行展开,然后对参数包里面的每一种参数类型再进行求和。

七、lambda表达式

介绍

Lambda表达式允许在需要函数对象(函数指针、函数符号)的地方使用内联函数,而不需要再单独的去定义一个函数或函数对象来实现某种简单的功能。

格式:

[capture](parameters) mutable -> return_type 
{
    CODE;  // Lambda函数的代码
}

  • capture:捕获列表,用于捕获外部变量。编译器根据[]来判断接下来的代码是否为lambda函数,捕捉列表能够捕捉上下文的变量供lambda函数使用。
  • parameters:与普通函数的参数列表类似,表示传递给Lambda函数的参数,没有参数需要传递就可以空着不写。
  • mutable:默认情况下,lambda函数总是一个const函数,mutable可以取消其常量
    性。使用该修饰符时,参数列表不可省略(即使参数为空)
  • return_type:Lambda函数的返回类型。没有返回值时此部分可省略,返回值类型明确情况下,也可省略,由编译器对返回类型进行推导
  • CODE:Lambda函数的实际代码。在该函数体内,除了可以使用其参数外,还可以使用所有捕获到的变量

lambda的参数列表和返回值类型都是可选部分,而捕捉列表和函数体可以为空。因此C++11中最简单的lambda函数为:[]{}; 但是该lambda函数不能做任何事情。
捕获列表说明:

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

注意:

  • 父作用域指包含lambda函数的语句块
  • 语法上捕捉列表可由多个捕捉项组成,并以逗号分割。比如:[=, &a, &b]:以引用传递的方式捕捉变量a和b,值传递方式捕捉其他所有变量; [&,a, this]:值传递方式捕捉变量a和this,引用方式捕捉其他变量
  • 捕捉列表不允许变量重复传递,否则就会导致编译错误。比如:[=, a]:=已经以值传递方式捕捉了所有变量,捕捉a重复
  • 在块作用域以外的lambda函数捕捉列表必须为空。
  • 在块作用域中的lambda函数仅能捕捉父作用域中局部变量,捕捉任何非此作用域或者非局部变量都会导致编译报错。

示例:

int main()
{
    // 最简单的lambda表达式, 该lambda表达式没有任何意义
    []{};

    // 省略参数列表和返回值类型,返回值类型由编译器推导为int
    int a = 3, b = 4;
    [=]{return a + 3; };

    // 省略了返回值类型,无返回值类型
    auto fun1 = [&](int c){b = a + c; };
    fun1(10);
    cout<<a<<" "<<b<<endl;    // 3 13

    // 各部分都很完善的lambda函数
    auto fun2 = [=, &b](int c)->int{return b += a+ c; };
    cout<<fun2(10)<<endl;  // 26

    // 复制捕捉x
    int x = 10;
    auto add_x = [x](int a) mutable { x *= 2; return a + x; };
    cout << add_x(10) << endl;  // 30

    return 0;
}

通过lambda写一个自定义排序: 

//商品类
struct Goods
{
	string _name;  // 名字
	double _price; // 价格
	int _eval; // 评价
};

//按价格的升序
struct Cmpup
{
	bool operator()(const Goods& g1, const Goods& g2)
	{
		return g1._price < g2._price;
	}
};

//按价格降序
struct Cmpdest
{
	bool operator()(const Goods& g1, const Goods& g2)
	{
		return g1._price > g2._price;
	}
};

int main()
{
	vector<Goods> v = { { "苹果", 2.1, 300 }, { "香蕉", 3.3, 100 }, { "橙子", 2.2, 1000 }, { "菠萝", 1.5, 1 } };
	
	sort(v.begin(), v.end(), Cmpup());    //按价格升序排序
	sort(v.begin(), v.end(), Cmpdest()); //按价格降序排序

	// 使用lambda表达式自定义排序
	sort(v.begin(), v.end(), 
		[](const Goods& g1, const Goods& g2) {return g1._price < g2._price; }); 
	sort(v.begin(), v.end(), 
		[](const Goods& g1, const Goods& g2) {return g1._price > g2._price; });
	sort(v.begin(), v.end(), 
		[](const Goods& g1, const Goods& g2) {return g1._eval < g2._eval; });
	sort(v.begin(), v.end(), 
		[](const Goods& g1, const Goods& g2) {return g1._eval > g2._eval; });

	return 0;
}

八、包装器 std::function

函数包装器 `std::function` 是C++11中的一个重要特性,它提供了一种能够存储和调用可调用对象(函数、函数指针、成员函数、lambda表达式等)的通用方式。std::function 是一个模板类,它可以用来封装各种不同类型的函数或可调用对象,从而实现了一种统一的接口来进行函数调用。

使用的头文件

#include <functional>

 格式:

#include <functional>

std::function<return_type(parameter_types)> func;
  • return_type:函数的返回类型。
  • parameter_types:函数的参数类型列表。
  • funcstd::function 类型的对象,可以用来存储和调用可调用对象。

示例:

#include <functional>
using namespace std;

// 普通函数
void printHello() {
    std::cout << "Hello, ";
}

void printWorld() {
    std::cout << "world!" << std::endl;
}


int add(int a, int b) {
    return a + b;
}

int main() {
    // 存储不同的函数
    std::vector<std::function<void()>> tasks;
    tasks.push_back(printHello);
    tasks.push_back(printWorld);
    for (const auto& task : tasks) {
        task(); // 调用存储的函数  会分别调用printHello和printWorld两个函数
    }

    // 存储普通函数
    std::function<int(int, int)> func = add;
    std::cout << func(3, 4) << std::endl;  // 输出 7

    // 存储lambda表达式
    std::function<int(int)> square = [](int x) -> int {
        return x * x;
    };
    std::cout << square(5) << std::endl;    // 输出 25

    return 0;
}

九、 右值引用

介绍 

在了解右值引用前,需要先知道什么是左值引用?

左值是一个表示数据的表达式(如变量名或解引用的指针),我们可以获取它的地址+可以对它赋值,左值可以出现赋值符号的左边,右值不能出现在赋值符号左边。定义时const修饰符后的左值,不能给他赋值,但是可以取它的地址。左值引用就是给左值的引用,给左值取别名。

左值引用的语法:&

比如:

// 以下的p、b、c、*p都是左值
int* p = new int(0);
int b = 1;
const int c = 2;
// 以下几个是对上面左值的左值引用
int*& rp = p;
int& rb = b;
const int& rc = c;
int& pvalue = *p;

右值引用与左值引用就差不多相反:右值也是一个表示数据的表达式,如:字面常量、表达式返回值,函数返回值(这个不能是左值引用返回)等等,右值可以出现在赋值符号的右边,但是不能出现出现在赋值符号的左边,右值不能取地址,右值不可以直接修改。右值引用又可以分为两类:纯右值、将亡值。右值引用就是对右值的引用,给右值取别名。

所以:无论左值引用还是右值引用,都是给对象取别名。

右值引用语法:&&

// 以下几个都是常见的右值
10;  // 这种就是纯右值
x + y;  //这种就是将亡值,其实就是中间变量的过渡,过渡之后就消亡
fmin(x, y);  //也是将亡值

// 以下几个都是对右值的右值引用
int&& rr1 = 10;
double&& rr2 = x + y;
double&& rr3 = fmin(x, y);
// 这里编译会报错:error C2106: “=”: 左操作数必须为左值
10 = 1;
x + y = 1;
fmin(x, y) = 1;

左、右值引用比较

  • 左值引用只能引用左值,不能引用右值。
  • 但是const左值引用既可引用左值,也可引用右值。
  • 左值引用必须进行初始化
int main()
{
    // 左值引用只能引用左值,不能引用右值。
    int a = 10;
    int& ra1 = a; // ra为a的别名

    //int& ra2 = 10; // 编译失败,因为10是右值

    // const左值引用既可引用左值,也可引用右值。
    const int& ra3 = 10;
    const int& ra4 = a;
    return 0;
}
  • 右值引用只能右值,不能引用左值。
  • 但是右值引用可以move以后的左值
  • 右值引用必须进行初始化
int main()
{
    // 右值引用只能右值,不能引用左值。
    int&& r1 = 10;

    // error C2440: “初始化”: 无法从“int”转换为“int &&”
    // message : 无法将左值绑定到右值引用
    int a = 10;
    int&& r2 = a;

    // 右值引用可以引用move以后的左值
    int&& r3 = std::move(a);
    return 0;
}

十、完美转发

模板中的&&不代表右值引用,而是万能引用,其既能接收左值又能接收右值。模板的万能引用只是提供了能够接收同时接收左值引用和右值引用的能力,但是引用类型的唯一作用就是限制了接收的类型,后续使用中都退化成了左值,我们希望能够在传递过程中保持它的左值或者右值的属性, 这就需要用到完美转发。它解决了在函数模板中传递参数时丢失信息的问题, 完美转发使得函数模板能够将参数原封不动地传递给其他函数,包括其参数类型和值类型,同时保留参数的左值或右值属性。

std::forward()   // 完美转发在传参的过程中保留对象原生类型属性
void Fun(int &x){ cout << "左值引用" << endl; }

void Fun(const int &x){ cout << "const 左值引用" << endl; }

void Fun(int &&x){ cout << "右值引用" << endl; }

void Fun(const int &&x){ cout << "const 右值引用" << endl; }

// std::forward<T>(t)在传参的过程中保持了t的原生类型属性。
template<typename T>
void PerfectForward(T&& t)
{
    Fun(std::forward<T>(t));
}

int main()
{
    PerfectForward(10); // 右值
    int a;
    PerfectForward(a); // 左值
    PerfectForward(std::move(a)); // 右值
    const int b = 8;
    PerfectForward(b); // const 左值
    PerfectForward(std::move(b)); // const 右值
    return 0;
}

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深度学习处理文本(NLP)

文章目录 引言1. 反向传播1.1 实例流程实现1.2 前向传播1.3 计算损失1.4 反向传播误差1.5 更新权重1.6 迭代1.7 BackPropagation & Adam 代码实例 2. 优化器 -- Adam2.1 Adam解析2.2 代码实例 3. NLP任务4. 神经网络处理文本4.1 step1 字符数值化4.2 step 2 矩阵转化为向量…

HTML基础知识点

目录 ​编辑一、使用 vscode 二、研究代码的特点 三、HTML 常见标签 注释标签 标题标签 段落标签 换行标签 格式化标签 图片标签 超链接标签 表格标签 列表标签 表单标签&#xff1a; form 标签 input标签&#xff1a; select textarea标签&#xff1a; 无语…

【stable-diffusion使用扩展+插件和模型资源(下)】

插件模型魔法图片等资源&#xff1a;https://tianfeng.space/1240.html 书接上文&#xff1a;&#xff08;上&#xff09; 插件推荐 1.lobe theme lobe theme是一款主题插件&#xff0c;直接可以在扩展安装 界面进行了重新布局&#xff0c;做了一些优化&#xff0c;有兴趣的…

HDLBits-Verilog学习记录 | Verilog Language-Vectors

文章目录 11.vectors | vector012.vectors in more detail | vector113.Vector part select | Vector214.Bitwise operators | Vectorgates15.Four-input gates | Gates416.Vector concatenation operator | Vector317.Vector reversal 1 | Vectorr18. Replication operator | …

平衡二叉树的插入和删除(从现在开始摆脱旋转)

平衡二叉树是指任意节点的左子树和右子树高度之差的绝对值不超过1 一.插入操作 1.找到合适位置插入 2.从下到上&#xff0c;沿着插入节点与根节点的连线&#xff0c;找到不平衡的二叉树 以68为根节点的二叉树平衡&#xff0c;左右子树高度差为1 以60为根节点的二叉树不平衡&a…

【Adobe After Effects】关于ae点击空格不会播放反而回退一帧的解决方案

最近玩ae的时候遇见了一个小问题&#xff0c;就是有时候敲空格&#xff0c;视频没办法播放&#xff0c;反而会回退一帧&#xff0c;经过摸索发现了一个解决办法&#xff1a; 点击编辑---首选项 然后选择“音频硬件” 然后选择正确的默认输出&#xff0c;点击确定即可

Android 13 - Media框架(6)- NuPlayer::Source

Source 在播放器中起着拉流&#xff08;Streaming&#xff09;和解复用&#xff08;demux&#xff09;的作用&#xff0c;Source 设计的好坏直接影响到播放器的基础功能&#xff0c;我们这一节将会了解 NuPlayer 中的通用 Source&#xff08;GenericSource&#xff09;关注本地…

【LeetCode】224. 基本计算器

224. 基本计算器&#xff08;困难&#xff09; 方法&#xff1a;双栈解法 思路 我们可以使用两个栈 nums 和 ops 。 nums &#xff1a; 存放所有的数字ops &#xff1a;存放所有的数字以外的操作&#xff0c;/- 也看做是一种操作 然后从前往后做&#xff0c;对遍历到的字符做…

万字精讲——数据结构栈与队列必会OJ练习

W...Y的主页 &#x1f495; 代码库分享 &#x1f60a; 在之前的博客中&#xff0c;我们学习了栈与队列的基本内容&#xff0c;并且实现了栈与队列。今天我们进行刷题训练&#xff0c;走进栈与队列的世界中去感受一番&#xff01;&#xff01;&#xff01; 目录 括号匹配问题…

redis 7高级篇1 redis的单线程与多线程

一 redis单线程与多线程 1.1 redis单线程&多线程 1.redis的单线程 redis单线程主要是指Redis的网络IO和键值对读写是由一个线程来完成的&#xff0c;Redis在处理客户端的请求时包括获取 (socket 读)、解析、执行、内容返回 (socket 写) 等都由一个顺序串行的主线程处理…

【VsCode】SSH远程连接Linux服务器开发,搭配cpolar内网穿透实现公网访问(1)

文章目录 前言1、安装OpenSSH2、vscode配置ssh3. 局域网测试连接远程服务器4. 公网远程连接4.1 ubuntu安装cpolar内网穿透4.2 创建隧道映射4.3 测试公网远程连接 5. 配置固定TCP端口地址5.1 保留一个固定TCP端口地址5.2 配置固定TCP端口地址5.3 测试固定公网地址远程 前言 远程…

synchronized锁升级

在 Java SE 1.6中&#xff0c; 锁 一共有 4 种状 态 &#xff0c; 级别 从低到高依次是&#xff1a;无 锁 状 态 、偏向 锁 状 态 、 轻 量 级锁 状 态和重量 级锁 状 态 &#xff0c; 这 几个状 态 会随着 竞 争情况逐 渐 升 级 。 锁 可以升 级 但不能降 级 &#xff0c;意味…

mysql的登录与退出

mysql是c/s架构&#xff0c;意味着同时要有客户端和服务端 1 找到客户端。mysql.exe的安装目录 打开命令行 2 输入对应的服务器的ip&#xff0c;如果是本地&#xff0c;就是Localhost&#xff0c;如果是远程服务器&#xff0c;那就输入对应ip/域名。并且指定mysql监听的端口 …

workbench连接MySQL8.0错误 bad conversion 外部组件 异常

阿里云搭建MySQL实用的版本是8.0 本地安装的版本是: workbench 6.3 需要升级到&#xff1a; workbench 8.0 https://dev.mysql.com/downloads/workbench/

elment-ui中使用el-steps案例

el-steps案例 样式 代码 <div class"active-box"><div class"active-title">请完善</div><el-steps :active"active" finish-status"success" align-center><el-step title"第一步" /><…

SpringCloud入门实战(十四)Sentinel微服务流量防卫兵简介

&#x1f4dd; 学技术、更要掌握学习的方法&#xff0c;一起学习&#xff0c;让进步发生 &#x1f469;&#x1f3fb; 作者&#xff1a;一只IT攻城狮 &#xff0c;关注我&#xff0c;不迷路 。 &#x1f490;学习建议&#xff1a;1、养成习惯&#xff0c;学习java的任何一个技术…

2023年高教社杯数学建模思路 - 复盘:光照强度计算的优化模型

文章目录 0 赛题思路1 问题要求2 假设约定3 符号约定4 建立模型5 模型求解6 实现代码 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 问题要求 现在已知一个教室长为15米&#xff0c;宽为12米&…

Android相机-HAL-Rockchip-hal3

引言&#xff1a; 对于Android相机的 HAL层而言对上实现一套Framework的API接口&#xff0c;对下通过V4L2框架实现与kernel的交互。不同的平台会有不同的实现方案。主要是对Android HAL3的接口的实现。看看rockchip是怎么支持hal3的&#xff1f; 代码目录&#xff1a; hardw…

中文分词和tfidf特征应用

文章目录 引言1. NLP 的基础任务 --分词2. 中文分词2.1 中文分词-难点2.2 中文分词-正向最大匹配2.2.1 实现方式一2.2.2 实现方式二 利用前缀字典 2.3 中文分词-反向最大匹配2.4 中文分词-双向最大匹配2.5 中文分词-jieba分词2.5.1 基本用法2.5.2 分词模式2.5.3 其他功能 2.6 三…

【Java】基础练习(十一)

1.Poker 定义两个数组&#xff0c;一个数组存储扑克牌花色&#xff0c;另一个数组存储扑克牌&#xff08;A~K&#xff09;&#xff0c;输出52张扑克牌&#xff08;除大小王&#xff09; ♥A、♥2...&#xff08;1&#xff09;Poker类&#xff1a; package swp.kaifamiao.cod…