C++新版本特性

目录:

前言

C++11的常用新特性

auto类型推导:

 auto的限制:

auto的应用: 

decltype类型推导:

decltype的实际应用: 

使用using 定义别名: 

 支持函数模板的默认模板参数 :

 tuple元组:

列表初始化:

 lambda匿名函数:

lambda的实际应用 :

for循环:

constexpr: 

右值引用:

std::move

std::forward

nullptr

 std::bind

 std::function

C++14的常用新特性

模板变量: 

 别名模板:

泛型lambda和lambda初始化捕捉

放松对constexpr函数的限制

 deprecated标记:

二进制字面量和数位分隔符: 

 折叠表达式:

类模板参数推导: 

 auto占位的非类型模板形参:

 编译期constexpr if语句/constexpr的lambda表达式:

内联变量:

结构化绑定:

if初始化:

using声明语句可以声明多个名称:


前言

本篇博客分享,对于c++11,14,17的常用c++新版本特性~


C++11的常用新特性

auto类型推导:

C++赋予auto关键字新的含义,用它做于自动类型推导

使用了auto关键字后,编译器会在编译阶段自动推导出变量的类型 

基本使用语法:

auto name = value;

name是变量名字,value是变量的初始值

注意:auto只是一个占位符,在编译期间会被真正的类型所替代,并不违背C++中的变量名必须有明确类型这一规定,只是这个是编译器自动给你推导的 

 auto的限制:

  • auto 不能在函数的参数中使用(auto 要求必须对变量进行初始化)
  • auto 不能作用于类的非静态成员变量(也就是没有 static 关键字修饰的成员变量)中
  • auto 关键字不能定义数组
  • auto 不能作用于模板参数

auto的应用: 

范围for:

int main()
{std::vector<int> vi{ 3,5,1,6,7,2,8 };for (auto e : vi) {std::cout << e << " ";}return 0;
}//输出结果:3 5 1 6 7 2 8

以及泛型编程中~ 

decltype类型推导:

 auto 和 decltype 关键字都可以自动推导出变量的类型,但它们的用法是有区别的:

auto name = value;decltype(exp) name = value;

其中name便是变量名,value表示赋给变量的初值~~

auto 根据 = 右边的初始值value推导出变量的类型

decltype根据圆括号内的exp表达式推出变量类型,和 = 右边的value无关

TIP:auto变量一定要初始化,decltype不用,很好理解,auto推导他需要初始化才推得动 

decltype的实际应用: 

下面就是使用的decltype推导的类型,避免使用T::iterator获得容器迭代器指针,因为有些自己实现的容器并没有iterator 

使用using 定义别名: 

C++11中的using 写法跟typedef 等价

template<typename V>
using smap = std::map<std::string, V>;void test_using()
{smap<int> mp1;mp1["score"] = 100;mp1["age"] = 18;smap<string> mp2;mp2["name"] = "Merge";mp2["address"] = "CN";std::cout << mp1["age"] << ": " << mp1["score"] << endl;std::cout << mp2["name"] << ": " << mp2["address"] << endl;}// 输出:
// 18: 100
// Merge: CN

 支持函数模板的默认模板参数 :

 C++11 支持为函数模板中的参数设置默认值,在实际使用过程中,我们可以选择使用默认值,也可以尝试由编译器自行推导得到,还可以亲自指定各个模板参数的类型

template <typename R = int, typename T, typename U>
R func(T v1,U v2)
{return v1+v2;
}void testFunTemplate()
{auto r1=func(5.5,10);                    auto r2=func<double>(5.5,10);            auto r3=func<double, int, int>(5.5,10); cout<<"r1:"<<r1<<endl;cout<<"r2:"<<r2<<endl;cout<<"r3:"<<r3<<endl;
}

 tuple元组:

tuple的最大特点是:实例化的对象可以存储任意数量、任意类型的数据

例如要储存多个不同类型的元素时;需要函数返回多个数据的时,可以存储在tuple中后返回

void tuple_test()
{std::tuple<int, char> fir;std::tuple<int, char> mid(std::make_pair(2, '2'));      //{2,'2'}std::tuple<int, char> sec(1, '1');                      //右值初始化std::tuple<int, int, char> thd(make_tuple(6, 6, '6'));  //右值初始化std::tuple<int, char> fourth(sec);                      //左值初始化std::cout << std::get<0>(fourth) << " : " << std::get<1>(fourth) << std::endl;std::cout << std::get<0>(thd) << " : " << std::get<1>(thd) << " : " << std::get<2>(thd) << std::endl;
}
//输出:
//1 : 1
//6 : 6 : 6

列表初始化:

 在 C++11 中,初始化列表的适用性被大大增加了。它现在可以用于任何类型对象的初始化


class Base
{
public:Base(int){}};
int main()
{Base b1(123);Base b2 = 123;Base b3 = { 123 };Base b4{ 123 };//c++11加入return 0;
}//上述这些都是可以给定义的对象赋初值的

 lambda匿名函数:

C++11中引入了lambda~~

定义一个lambda匿名函数:

[](){}

这就是lambda的表达式三个括号,省略返回值

[外部访问方式说明符](参数){函数体};
外部变量格式                                          功能
[]        空方括号表示当前 lambda 匿名函数中不导入任何外部变量
[=]只有一个 = 等号,表示以值传递的方式导入所有外部变量
[&]只有一个 & 符号,表示以引用传递的方式导入所有外部变量
[val1,val2,...]表示以值传递的方式导入 val1、val2 等指定的外部变量,同时多个变量之间没有先后次序
[&val1,&val2,...]表示以引用传递的方式导入 val1、val2等指定的外部变量,多个变量之间没有前后次序
[val,&val2,...]以上 2 种方式还可以混合使用,变量之间没有前后次序
[=,&val1,...]表示除 val1 以引用传递的方式导入外,其它外部变量都以值传递的方式导入
[this]表示以值传递的方式导入当前的 this 指针

lambda的实际应用 :

 使用Lambda表达式在向量中查找大于10的元素并打印出来:


int main()
{vector<int> vi{ 1,4,21,12,13,9,30,24 };std::for_each(vi.begin(), vi.end(), [](int num){if (num > 10) std::cout << num << " ";});return 0;
}
//输出:21 12 13 30 24

 使用Lambda表达式实现自定义排序规则,并对一个字符串数组进行排序:


int main()
{vector<string> vs{ "Alice","Bob","Merial","Lucy","GorzenHot" };sort(vs.begin(), vs.end(), [](const string s1, const string s2) {return s1.size() < s2.size();});for (auto e : vs)cout << e << " ";return 0;
}
//输出:Bob Lucy Alice Merial GorzenHot

for循环:

 C++ 11 标准为 for 循环添加了一种全新的语法格式

for (declaration : expression){//循环体
}

示例即对于上面lambda的遍历方式~~

constexpr: 

constexpr关键字能够让指定的常量表达式在程序编译阶段计算出结果,而不需要到运行阶段
c++11中constexpr可用于修饰普通变量、函数、类的构造函数
int main()
{constexpr int num = 1 + 2 + 3;int arr[num]{ 1,2,3,4,5,6 };cout << arr[5];return 0;
}
//输出:5

右值引用:

C++11标准引入的另一种应用方式,称为右值引用。从而引出了移动语义和完美转发~~

声明和左值引用一样,右值引用也必须立即进行初始化操作,且只能使用右值进行初始化。

int num = 1;int && a = 10;a = 20;
cout<<a<<endl;
//输出:20

右值也必须使用右值进行初始化

std::move

C++11最重要的一个改进之一就是引入了move语义,这样在一些对象的构造时可以获取到已有的资源(如内存)而不需要通过拷贝,申请新的内存,这样移动而非拷贝将会大幅度提升性能

class Base {
public:Base():num(new int(0)){cout << "构造函数" << endl;}Base(const Base& b) :num(new int(*b.num)) {cout << "拷贝构造函数" << endl;}Base(Base&& b) :num(b.num) {b.num = nullptr;cout << "移动构造函数" << endl;}~Base() {delete num;cout << "析构函数" << endl;}
public:int* num;
};int main()
{int* num = new int(20);Base a;Base b(a);Base c(std::move(b));return 0;
}//构造函数
//拷贝构造函数
//移动构造函数//析构函数
//析构函数
//析构函数

在移动构造的时候,没有新的内存申请和分配,有的只是资源转移,在大量对象的系统中,移动构造相对拷贝构造可以显著提升性能!

std::forward

完美转发:函数模板可以将自己的参数“完美”的转发给内部调用接口,不仅仅能够转移参数的值,还能转移参数的左右属性不变~~

void FTest(int& t) {cout << "左值" << endl;
}
void FTest(int&& t) {cout << "右值" << endl;
}
template <typename T>
void func(T&& t) {FTest(std::forward<T>(t));
}void Test_Forward()
{string A = "abc";string&& Rval = std::move(A);string B(Rval);       //拷贝构造,不是移动构造cout << A << endl;    //此时A的资源已经被转移到 Rval了string C(std::forward<string>(Rval));//移动构造,保留了Rval的属性为右值,否则如果不在这 //里std::move()的话,并不能完美转发属性func(5);int x = 1;func(x);
}//输出结果: abc
//          右值
//          左值

nullptr

C++11下,相比于NULL和0,使用nullptr初始化空指针,可以使我们编写的程序更健壮


void isnull(void* c) {cout << "void*c" << endl;
}
void isnull(int n) {cout << "int n" << endl;
}void testNullptr()
{cout << "testNullptr:" << endl;isnull(0);//isnull(NULL); // C++ 98/03 标准中 输出 int nisnull(nullptr);
}int main() {testNullptr();return 0;
}
//输出:testNullptr:
//     int n
//     void*c

 std::bind

std::bind

函数原型:

template<class Fn, class... Args>
std::bind(Fn&& fn, Args&&... args);

对其参数的解释:

  • Fn:是要绑定的可调用对象(函数,函数指针,成员函数,函数对象等)
  • Args:是对应Fn的参数列表 

std:bind函数返回一个新的可调用对象,可以同股调用该对象执行绑定的函数,并传递额外的参数.

示例:

void foo(int a, int b)
{cout << "a: " << a << "\t" << "b: " << b << endl;std::cout << "Sum : " << a + b << endl;
}
int main() {auto SumFunc = std::bind(foo,placeholders::_1,10);SumFunc(10);return 0;
}//输出: a: 10   b: 10
//      Sum : 20

每个参数都可以绑定一个值或是占位符上:

  • 如果绑定一个值,那么调用返回的函数对象就会使用该值作为参数
  • 如果是一个占位符,则调用返回的函数对象会转发一个传递给调用的参数(参数顺序由占位符决定)

 std::bind的注意事项:

  • bind预先绑定的参数需要传递具体的变量或者值进去,对于预先绑定的参数是pass-by-value。除非被std::cref包装,才pass-by-reference
  • 对于事先不绑定的参数,就需要传入std::placeholders进去从 _1开始递增,这些placeholder是pass-by-reference的
  • bind的返回值是可调用的实体,可以赋值给std::function对象
  • 对于绑定的指针、引用类型参数,需要保证在调用实体之前,这些参数是可用的
  • 类的this可以通过对象或者指针来绑定

 std::function

类模板std::function是一种通用、多态的函数封装。std::function的示例可以对任何可调用的目标实体进行存储、复制、调用和操作。这些包括 普通函数、lambda表达式,bind表达式、函数指针及其他函数对象~~


C++14的常用新特性

模板变量: 

在C++14中:

  •  lambda表达式参数可以为auto类型 ,类似于函数模板
  • 可以对捕捉列表的捕获变量“赋值”
template<typename T>
constexpr T pi = T(3.1415926535897932385); //变量模板template<typename T>
T circular(T r) {return pi<T> *r * r;
}
int main()
{cout << circular(2) << endl;cout << circular(2.00) << endl;return 0;
}//输出: 12
//      12.5664

 别名模板:


template<typename T ,typename U>
struct A {T t;U u;
};template<typename T>
using B = A<T, int>;int main()
{B<double> b;b.t = 12.12;b.u = 34.12;cout << b.t << " " << b.u << endl;
}//输出:12.12 34
//这里模板U已经被特化成int 类型,并且定义新的别名模板 B
//从此B就是一个T类型 加 一个 int 类型 的A模板

泛型lambda和lambda初始化捕捉

int main()
{int a = 2;auto fa = [a = sin(a)]() {cout << a << endl;cout << cos(a) << endl;};fa();cout << a << endl;//lambda表达式中参数可以为auto了auto f = [](auto a) {return a;};cout << f(1.1) << " " << f(298) << endl;return 0;
}
//输出结果:
// 0.909297
// 0.6143
// 2
// 1.1 298

放松对constexpr函数的限制

C++11中的常量表达式函数:

  • 函数体只有单一的return返回语句
  • 函数必须有返回值(不能是void函数)
  • 在使用前必须有定义
  • return返回语句表达式中不能使用非常量表达式的函数,全局数据,必须是一个常量表达式
#include <cmath>
#include <iostream>
using namespace std;constexpr int factorial(int n) { // 在C++11或者C++14中均可以编译通过return n <= 1 ? 1 : (n * factorial(n - 1));
}constexpr int factorial_c14(int n) { // 只有在C++14中可以编译通过int ret = 1;for (int i = 1; i <= n; ++i) {ret *= i;}return ret;
}int main()
{std::cout << factorial(5) << std::endl;   // 120std::cout << factorial_c14(5) << std::endl; // 在c++11下,会报error: body of ‘constexpr’ function ‘constexpr int factorial_c14(int)’ not a return-statementreturn 0;
}

 deprecated标记:

C++14中增加了[[deprecated]]标记,可以修饰类、函数、变量等,当程序中使用了被其修饰的模块时,编译器会产生告警,提示用户该标记标记的内容将来可能会被废弃,尽量不要使用

二进制字面量和数位分隔符: 

int main()
{int a = 0b0001'1111'1010;double b = 3.14'1592'6535;cout << a << " " << b << endl;return 0;
}
//输出:506 3.14159

 折叠表达式:

template <typename... Args>
auto sub_right(Args... args)
{return (args - ...);
}template<typename... Args>
auto sub_left(Args... args)
{return (... - args);
}
template<typename... Args>
auto sum_right(Args... args)
{return (args + ...);
}int main()
{cout << sub_right(10, 6, 4) << endl; //(10 - (6 -4)) = 8cout << sub_left(10, 6, 4) << endl;  //((10 - 6) - 4)= 0cout << sum_right(10, 6, 4) << endl; //(10 + ( 6 + 4 )) = 20return 0;
}
//输出:8 0 20

类模板参数推导: 

类模板实例化时,可以不必显示指定类型,前提是保证类型可被推导

template<typename T>
class A {
public:A(T,T){}
};int main() {auto a = new A{ 1,2 };   //A<int> A<int> *b = new A(3, 4); //A<int> std::tuple t(3, 4, 5.6); //std::tuple<int,int,double> t
}

 auto占位的非类型模板形参:

template<auto T>
void foo()
{cout << T << endl;
}int main()
{foo<100>();return 0;
}
//输出: 100

 编译期constexpr if语句/constexpr的lambda表达式:

lambda表达式可以再编译期进行运算,且函数体不能包含汇编语句,goto语句,try块,静态变量,线程局部存储,没有初始化的普通变量,不能动态分配内存,不能new delete等,不能为虚函数 

#include <assert.h>template<auto flag>constexpr void foo()
{//在编译期间进行判断,if和else语句不生成代码if constexpr (flag == true) {       //当flag为true的时候,下面的else块不生成汇编代码cout << "flag == true" << endl;}else  {cout << "flag == false" << endl;}
}
int main() {foo<true>(); //输出flag == true ,并且汇编代码中只有 cout<<"flag == true"<<endl;constexpr auto foo = [](int a, int b) {return a + b;};static_assert(foo(2, 3) == 5, "compile-time assert");//静态断言,用于编译期的断言return 0;
}

 static_assert:是静态断言,在编译期的断言,而constexpr就可以在编译期得到结果,从而提前判断.

内联变量:

扩展的inline用法,使得可以在头文件或者类内初始化静态成员变量:


// test.h
inline int val = 1;// test.cpp
struct A
{inline static int val = 1;
};  

结构化绑定:

在C++11中,如果需要获取tuple元素,需要使用get<>()函数或者tie<>函数,这个函数可以把tuple中的元素转化为可以绑定到tie<>()左值的集合。

C++17中的结构化绑定,大大方便了这种操作,而且使用引用捕捉时还可以修改捕捉对象的值

#include<unordered_map>
#include<tuple>void test1() {tuple person = std::make_tuple(string{ "XiaoHei" }, 26, string{ "man" });string name;int age;string gender;tie(name, age, gender) = person;cout << name << " " << age << " " << gender << endl;
}struct Student {string name;int age;
};Student getStudent() {return { "xiaobai",22 };
}
void test2()
{tuple stu = make_tuple(string("Xiaohei"), 18, string("man"));auto [name, age, gender] = stu;//这里的auto推导出//std::tuple<string,int,string> 类型cout << name << " " << age << " " << gender << endl;//这是按tuple 的结构化绑定auto [_name, _age] = getStudent();//这个stu就被推成一个pair 类形了auto stu_cls = getStudent();cout << _name << " " << _age << endl;unordered_map<string, int> mstu;mstu.emplace("张三", 33);mstu.emplace("李四", 44);for (auto [name, age] : mstu) {cout << name << " " << age << endl;}}   int main()
{test1();test2();return 0;
}

使用结构化绑定,可以将一个复杂对象(元组,map,make_pair,包含多个成员的结构体 等)分解其各个成员,并将这些成员绑定到对应的变量当中,无需显示的通过函数或者成员访问来获取每个成员的值.

if初始化:

#include <iostream>
#include <unordered_map>
#include <tuple>void c11_fun()
{std::unordered_map<std::string, int> students{{"liBai", 18}, {"hanXin", 19}};auto iter = students.find("hanXin");if (iter != students.end()){std::cout << iter->second << std::endl;}
}void c17_fun()
{std::unordered_map<std::string, int> students{{"liBai", 18}, {"hanXin", 19}};if (auto iter = students.find("hanXin"); iter != students.end()){std::cout << iter->second << std::endl;}
}int main()
{//c11_fun();c17_fun();return 0;
}

using声明语句可以声明多个名称:

using std::cout , std::endl;

 

 

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

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

相关文章

泛型相关内容

1. 什么是泛型 泛型就是定义一种模板&#xff0c;既实现了编写一次&#xff0c;万能匹配&#xff0c;又通过编译器保证了类型安全。 2. 使用泛型 1&#xff09;使用泛型时&#xff0c;把泛型参数<T>替换为需要的class类型&#xff0c;不指定时默认为Obje…

uniapp中配置开发环境和生产环境

uniapp在开发的时候&#xff0c;可以配置多种环境&#xff0c;用于自动切换IP地址&#xff0c;用HBuilder X直接运行的就是开发环境&#xff0c;用HBuilder X发布出来的&#xff0c;就是生产环境。 1.使用HBuilder X创建原生的uniapp程序 选择vue3 2.什么都不改&#xff0c;就…

可达鸭二月月赛——入门赛第四场(周三)题解

可达鸭二月月赛——入门赛第四场&#xff08;周三&#xff09;题解 博文作者&#xff1a;王胤皓 题目&#xff08;可达鸭学员应该能打开&#xff0c;打不开的题解里有题目简述&#xff09;题解(点击即可跳转&#xff0c;里面有我的名字)T1 小可喝水linkT2 \texttt{ }\texttt{ …

06-OpenFeign-使用HtppClient连接池

默认下OpenFeign使用URLConnection 请求连接&#xff0c;每次都需要创建、销毁连接 1、添加ApacheHttpClient依赖 <!-- 使用Apache HttpClient替换Feign原生httpclient--><dependency><groupId>org.apache.httpcomponents</groupId><artifact…

音视频色彩:RGB/YUV

目录 1.RGB 1.1介绍 1.2分类 1.2.1RGB16 1)RGB565 2)RGB555 1.2.2RGB24 1.2.3RGB222 2.YUV 2.1介绍 2.2分类 2.2.1 YUV444 2.2.2 YUV 422 2.2.3 YUV 420 2.3存储格式 2.3.1 YUYV 2.3.2 UYVY 2.3.3 YUV 422P 2.3.4 YUV420P/YUV420SP 2.3.5 YU12 和…

百卓Smart管理平台 uploadfile.php 文件上传漏洞【CVE-2024-0939】

百卓Smart管理平台 uploadfile.php 文件上传漏洞【CVE-2024-0939】 一、 产品简介二、 漏洞概述三、 影响范围四、 复现环境五、 漏洞复现手动复现小龙验证Goby验证 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工…

【Linux】vim的基本操作与配置(上)

Hello everybody!今天我们要进入vim的讲解了。学会了vim,咱们就可以在Linux系统上做一些简单的编程啦&#xff01; 那么废话不多说&#xff0c;咱们直接进入正题&#xff01; 1.初识vim vim是一款多模式的文本编辑器&#xff0c;可以对一个文件进行编辑操作。 它一共有三个模…

Visual Studio 2022中创建的C++项目无法使用万能头<bits/stdc++.h>解决方案

目录 发现问题 解决办法 第一步 第二步 第三步 第四步 最后一步 问题解决 发现问题 如果大家也遇到下面这种问题&#xff0c;可能是没有include文件夹中没有bits/stdc.h 解决办法 第一步 打开一个C项目&#xff0c;鼠标移动至头文件上右击&#xff0c;选择转到文档或…

Docker Compose 构建 LNMP 环境:一站式 PHP 网站部署指南

Docker Compose 构建 LNMP 环境&#xff1a;一站式 PHP 网站部署指南 简介环境准备和安装安装 Docker安装 Docker Compose准备项目目录结构 编写 Docker Compose 文件基础结构配置 Nginx 服务配置 PHP 服务配置 MySQL 服务完整的 docker-compose.yml 示例 Nginx 容器配置创建 N…

微信自动预约小程序开发指南:从小白到专家

随着互联网的发展&#xff0c;小程序已经成为了一个备受欢迎的在线预约平台。本文将详细介绍如何使用第三方制作平台&#xff0c;如乔拓云网&#xff0c;来搭建一个从入门到精通的预约小程序。 首先&#xff0c;我们需要登录乔拓云网&#xff0c;并选择一个适合自己的小程序模板…

PdfFactory Pro软件下载以及序列号注册码生成器

PdfFactory Pro注册机是一款针对同名虚拟打印机软件所推出的用户名和序列号生成器。PdfFactory Pro是一款非常专业的PDF虚拟打印软件&#xff0c;通过使用这款注册机&#xff0c;就能帮助用户免费获取注册码&#xff0c;一键激活&#xff0c;永久免费使用。 pdffactory7注册码如…

Node.js之npm单独与批量升级依赖包的方式

Node.js之npm单独与批量升级依赖包的方式 文章目录 Node.js之npm单独与批量升级依赖包的方式npm查看与升级依赖包1. 单独安装或升级最新版本2. 查看依赖但不升级1. npm outdated2. npm update 3. 批量升级新版本4. npm-check-updates1. 全局安装2. ncu查看可升级的版本3. 升级依…

购物车商品数量为0判断是否删除

当编辑商品的数量为1&#xff0c;再减的话&#xff0c;我们搞个模态提示&#xff0c;让用户决定是否要删除这个商品&#xff1f; //商品数量的编辑功能handleItemNumEdit(e){const {operation,id}e.currentTarget.dataset;console.log(operation,id);let {cart}this.data;let …

特征工程:特征提取和降维-下

目录 一、前言 二、正文 Ⅰ. 流形学习 Ⅱ.t-SNE Ⅲ.多维尺度分析 三、结语 一、前言 通过上篇对线性与非线性的数据的特征提取和降维的学习之后&#xff0c;我们来介绍其他方法&#xff0c;分别有流行学习、多维尺度分析、t-SNE。 二、正文 Ⅰ. 流形学习 流形学习是借鉴拓…

《向量数据库指南》——Milvus Cloud「删除」:眼见未必为实

“执行 Collection 中的 delete 操作后,再次调用 num_entities 检查集合中的数据的条数,和删除前一致, delete 不能从物理层面上删除数据吗?”“删除的数据还能被查到是为什么?”“请问下删除 collection 后,磁盘大小没有恢复,该怎么处理?”社区中关于“删除”讨论最多…

MyBatisPlus基础操作之增删改查

目录 一、基本使用 1.1 插入数据 1.2 删除操作 1.3 更新操作 二、条件构造器Wrapper 2.1 常用AbstractWrapper方法 2.1.1 示例一 2.2.2 示例二 2.2.3 示例三 2.2 常用QueryWrapper方法 2.2.1 示例一 2.2.2 示例二 2.2.3 示例三&#xff08;常用&#xff09; 2.3 常…

浅谈垃圾回收、内存泄漏与闭包

什么是垃圾&#xff1f; 在js中&#xff0c;垃圾通常指的是不再被程序使用的内存或对象。也就是说&#xff0c;垃圾是指程序中分配的内存空间或对象&#xff0c;但不再被程序使用或无法被访问到的内容 function createIncrease() {const doms new Array(100000).fill(0).map((…

形态学算法之边界提取的简单python实现——图像处理

原理 图像处理中的边界提取是一项基本而重要的任务&#xff0c;主要用于识别和提取图像中物体的轮廓或边界。 具体流程 1.边缘检测 边界提取的第一步通常是边缘检测。边缘是图像亮度变化显著的地方&#xff0c;是物体与背景或不同物体间的分界线。边缘检测算法通过识别图像中…

EMC学习笔记(二十一)降低EMI的PCB设计指南(一)

降低EMI的PCB设计指南&#xff08;一&#xff09; 1.概述2.射频3.连接器与过孔元件4.静态引脚和动态引脚和输入5.基本回路6.差模与共模 tips&#xff1a;资料主要来自网络&#xff0c;仅供学习使用。 1.概述 印刷电路板(PCB)的一般布局准则&#xff0c;基本上都有相对的文件进…

2024.02.07作业

请编程实现二叉树的操作 1.二叉树的创建 typedef struct a {char data;struct a* lchild;struct a* rchild; } *Node;Node create_node() {Node node (Node)malloc(sizeof(struct a));if (NULL node){return NULL;}node->lchild NULL;node->rchild NULL;return …