C++11特性详解

news2024/11/25 3:05:01

一、简介

在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;
}

 

 

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

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

相关文章

通过Putty对Linux服务器进行文件的上传与下载

1、下载安装Putty&#xff0c;下载地址&#xff1a;https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html 2、打开cmd窗口&#xff0c;通过命令行进入安装路径&#xff0c;如&#xff1a; 3、上传文件 pscp 文件 用户名服务器ip:目录使用“ -l ”选项可以指定用户…

keepalived+lvs(DR)

目录 一&#xff0c;作用 二&#xff0c;调度器配置 1&#xff0c;安装keepalived 2&#xff0c; 安装ipvsadm 3&#xff0c; 配置keepalived 4. 查看lvs节点状态 5&#xff0c; web节点配置 1.1 调整ARP参数 1.2 配置虚拟IP地址 1.3添加回环路由 1.4安装nginx并写…

【Unity学习笔记】DOTween(2)官方案例

本文中大部分内容学习来自DOTween官方文档 此处无法展示动图&#xff08;懒得录GIF&#xff09;&#xff0c;请下载官方案例场景自行学习 文章目录 场景1 基本补间场景2 动态补间场景3 Shader修改场景4 路径拟合运动场景5 序列播放场景6 UGUI 场景1 基本补间 案例一展示了最基…

技术博客写作「个人经验分享」

技术博客写作「个人经验分享」 仔细想来&#xff0c;从19年我刚开始试着技术写作算起&#xff0c;已经过去了好几年时间。刚好趁着这次的[赠送奖牌活动(奖牌很好看&#xff0c;我很想要hhh&#x1f602;)],来分享一下我关于技术博客写作的一些个人经验~ 文章目录 技术博客写作「…

k8s 常用命令(四)

12、删除pod中的nginx服务及service [rootmaster ~]# kubectl delete deployment nginx -n kube-public [rootmaster ~]# kubectl delete svc -n kube-public nginx-service 13、查看endpoint的信息 [rootmaster ~]# kubectl get endpoints 14、修改/更新&#xff08;镜像、…

内网穿透实战应用-windwos10系统搭建我的世界服务器,内网穿透实现联机游戏Minecraft

文章目录 1. Java环境搭建2.安装我的世界Minecraft服务3. 启动我的世界服务4.局域网测试连接我的世界服务器5. 安装cpolar内网穿透6. 创建隧道映射内网端口7. 测试公网远程联机8. 配置固定TCP端口地址8.1 保留一个固定tcp地址8.2 配置固定tcp地址 9. 使用固定公网地址远程联机 …

Unbutu系统-Docker安装、JDK环境配置,Docker常用指令、Docker安装MySQL、Redis、Tomcat、Nginx,前端后分离项目部署

目录 1、防火墙 1.1、查看防火墙状态 1.2、开启防火墙 1.3、关闭防火墙 1.4、重启防火墙 1.5、查看防火墙版本 2、安装JDK 2.1、官网下载tar包 2.3、解压tar.gz文件 2.4、配置环境变量 2.4.1、查看安装路径 2.4.2、设置环境变量 2.4.3、执行该让环境变量生效 2.4…

vue2.6及以下版本导入 TDesign UI组件库

TDesign 官方文档:https://tdesign.tencent.com/vue/components/button 我们先打开一个普通的vue项目 然后 如果你是 vue 2.6 或者 低于 2.6 在终端执行 npm i tdesign-vue如果你是 2.7 或者更高 执行 npm i tdesign-vuenaruto这里 我们 以 2.6为例 因为大部分人 用vue2 都是…

华为“天才少年”稚晖君发布具身智能机器人远征A1,引领智能科技新时代!

原创 | 文 BFT机器人 继前几天小米发布仿生四足机器人CyberDog2之后&#xff0c;2023年8月18日上午&#xff0c;被称为“华为天才少年”、“野生钢铁侠”的彭志辉&#xff0c;也就是B站硬核科技UP主稚晖君。 他目前担任智元CTO和首席架构师&#xff0c;他和他的智元团队创业半…

【C++STL入门】vector查、改、交换

文章目录 前言一、查1.1 输出全部迭代器下标运算for_each函数 1.2 输出单个元素at()函数[] 下标运算back()函数 二、改assign函数 三、交换swap函数 总结 前言 一、查 在C中&#xff0c;使用vector进行查找操作可以分为两类&#xff1a;输出全部和输出单个元素。下面将详细介绍…

音视频FAQ(二)视频直播延时高

摘要 延时高是实时互动技术中常见的问题之一&#xff0c;解决延时高问题需要综合考虑网络、设备、编解码算法等多个因素。解决方案包括优化设备端延时、优化网络传输延时和使用UDP进行音视频传输等。在选择音视频传输协议时&#xff0c;需要综合考虑实际需求和网络条件&#x…

图神经网络与分子表征:2. SchNet

SchNet 在2018年的面世彻底引爆了神经网络势函数(NNP, Neural Network Potential)领域&#xff0c;虽然说NNP的开山鼻祖还要更早&#xff0c;但均未像 SchNet 这样真正被物理化学家接受&#xff0c;引发变革。 这篇博客浅浅记录下自己阅读SchNet代码的心得。2023年的今天&…

如何五分钟设计制作自己的蛋糕店小程序

在现如今的互联网时代&#xff0c;小程序已成为企业推广和销售的重要利器。对于蛋糕店来说&#xff0c;搭建一个小程序可以为其带来更多的品牌曝光和销售渠道。下面&#xff0c;我们将以乔拓云平台为例&#xff0c;来教你如何从零开始搭建自己的蛋糕店小程序。 首先&#xff0c…

Mybatis分页及特殊字符

目录 MyBatis分页 特殊字符 接着上篇博客接下来我们要写的是MyBatis分页 MyBatis分页 首先我们导入pom依赖 <dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.1.2</version>…

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

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

基于 SVG 的图形交互方案实践

不知道从什么时候起&#xff0c;人们开始喜欢上数字大屏这种“花里胡哨”的东西&#xff0c;仿佛只要用上“科技蓝”这样神奇的色调&#xff0c;就可以让一家公司焕然一新&#xff0c;瞬间变得科技感满满。不管数字大屏的实际意义&#xff0c;是用来帮助企业监控和决策&#xf…

压力传感器丨定义、原理、应用

压力传感器是工业实践中常用的设备&#xff0c;作为自控系统的重要组成部分&#xff0c;压力传感器能够用于工业过程中压力参数的测量和控制&#xff0c;常用于高温、低压、腐蚀、振动等环境。 压力传感器的原理是基于压力感测技术&#xff0c;能够将被测压力转化为4G信号&…

开学日临近,送你一份VR校园攻略

开学日临近&#xff0c;各位萌新是否还在心怀激荡&#xff0c;无限憧憬着美丽校园呢&#xff1f;可能有一部分大学已经开学了&#xff0c;那么刚入校园的你们&#xff0c;是不是也想尽快熟悉未来学习、生活的地方呢&#xff1f;这份VR校园攻略带你沉浸式体验校园生活。 首先是大…

基于前端技术原生HTML、JS、CSS 电子病历编辑器源码

电子病历系统采取结构化与自由式录入的新模式&#xff0c;自由书写&#xff0c;轻松录入。实现病人医疗记录&#xff08;包含有首页、病程记录、检查检验结果、医嘱、手术记录、护理记录等等。&#xff09;的保存、管理、传输和重现&#xff0c;取代手写纸张病历。不仅实现了纸…

亚马逊出口灯具需要做的认证fcc认证UL认证ROHS认证CE认证

灯具CE认证&#xff1a; ​CE认证是产品进入欧盟及欧洲贸易自由区国家市场的通行证。任何国家的产品要进入欧盟、欧洲自由贸易区必须进行CE认证&#xff0c;在产品上加贴CE标志。LED灯具CE认证检测&#xff0c;为各国产品在欧洲市场进行贸易提供了统一的技术规范&#xff0c;C…