当前位置: 首页 > news >正文

C++新增的类功能和可变参数模板

在这里插入图片描述

C++新增的类功能和可变参数模板

  • 新的类功能
    • 默认成员函数
  • 可变参数模板
  • 模拟实现emplace_back

🌏个人博客主页: 个人主页

在这里插入图片描述

新的类功能

默认成员函数

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

  1. 构造函数
  2. 析构函数
  3. 拷贝构造函数
  4. 拷贝赋值重载
  5. 取地址重载
  6. const 取地址重载

在这里插入图片描述

最后重要的是前4个,后两个用处不大。默认成员函数就是我们不写编译器会生成一个默认的。C++11 新增了两个:移动构造函数和移动赋值运算符重载

为了方便观察我们写一个简单的string

class string
{public:typedef char* iterator;iterator begin(){return _str;}iterator end(){return _str + _size;}typedef const char* const_iterator;const_iterator begin() const{return _str;}const_iterator end() const{return _str + _size;}string(const char* str = ""):_size(strlen(str)), _capacity(_size){cout << "string(char* str)" << endl;_str = new char[_capacity + 1];strcpy(_str, str);}// s1.swap(s2)void swap(string& s){::swap(_str, s._str);::swap(_size, s._size);::swap(_capacity, s._capacity);}// 拷贝构造// s2(s1)string(const string& s):_str(nullptr){cout << "string(const string& s) -- 深拷贝" << endl;reserve(s._capacity);for (auto ch : s){push_back(ch);}}// 移动构造// 临时创建的对象,不能取地址,用完就要消亡// 深拷贝的类,移动构造才有意义string(string&& s):_str(nullptr){cout << "string(string&& s) -- 移动拷贝" << endl;swap(s);}// 赋值重载string& operator=(const string& s){cout << "string& operator=(const string& s) -- 深拷贝" << endl;if (this != &s){_str[0] = '\0';_size = 0;reserve(s._capacity);for (auto ch : s){push_back(ch);}}return *this;}// 移动赋值string& operator=(string&& s){cout << "string& operator=(string&& s) -- 移动赋值" << endl;swap(s);return *this;}~string(){cout << "~string()" << endl;delete[] _str;_str = nullptr;}char& operator[](size_t pos){assert(pos < _size);return _str[pos];}void reserve(size_t n){if (n > _capacity){char* tmp = new char[n + 1];if (_str){strcpy(tmp, _str);delete[] _str;}_str = tmp;_capacity = n;}}void push_back(char ch){if (_size >= _capacity){size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newcapacity);}_str[_size] = ch;++_size;_str[_size] = '\0';}//string operator+=(char ch)string& operator+=(char ch){push_back(ch);return *this;}const char* c_str() const{return _str;}private:char* _str = nullptr;size_t _size = 0;size_t _capacity = 0; // 不包含最后做标识的\0};
}

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

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

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

在这里插入图片描述

为什么这里的条件怎么苛刻呢?

因为如果一个类需要显示写析构说明有资源需要释放,那么通常就要写析构函数,拷贝构造,拷贝赋值运算重载,对资源进行管理,假如一个类是由自定义类型和内置类型构成的,对于内置类型不需要进行资源管理,只要完成值拷贝就可以了,而且要不用释放资源,对于自定义类型,如果由资源需要管理,我们只需要调用它对应写的函数即可,这样就不用我们单独写了,例如:Person类。

所以这里的条件是合理的。

如果你没有自己实现移动赋值重载函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中的任意一个,那么编译器会自动生成一个默认移动赋值。

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

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

在这里插入图片描述

如果你提供了移动构造或者移动赋值,编译器不会自动提供拷贝构造和拷贝赋值。


class Person
{
public:Person(const char* name = "", int age = 0):_name(name),_age(age){}Person(Person&& s) = default;
private:string _name;int _age;
};int main()
{Person s1("Peter",18);Person s2 = s1;//errreturn 0;
}

因为如果我们不写拷贝构造,编译器就会生成默认的拷贝构造,对于内置类型完成值拷贝,对应自定义类型对调用其对应的拷贝构造,但是如果我们显示写了移动构造,编译器会把移动构造当做拷贝构造的一种,就不会生成默认的拷贝构造,只能完成右值对应的拷贝。

强制生成默认函数的关键字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:string _name;int _age;
};

禁止生成默认函数的关键字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& s) = delete;Person(Person&& s) = delete;
private:string _name;int _age;
};

我们只需要禁用拷贝构造或者移动构造中的一个另一个就不会自动生成,赋值重载也是同样的道理。

在这里插入图片描述

可变参数模板

C++11的新特性可变参数模板能够让您创建可以接受可变参数的函数模板和类模板。

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

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

上面的参数args前面有省略号,所以它就是一个可变模版参数,我们把带省略号的参数称为“参数包”,它里面包含了0到N(N>=0)个模版参数。我们无法直接获取参数包args中的每个参数的,只能通过展开参数包的方式来获取参数包中的每个参数。

递归函数方式展开参数包

void ShowList()
{cout << endl;
}template <class T, class ...Args>
void ShowList(const T& val, Args... args)
{cout << val << " ";ShowList(args...);
}int main()
{ShowList();ShowList('x');ShowList('x', 'y');ShowList(1,'x', 'y');
}

逗号表达式展开参数包

template <class T>
void PrintArg(T t)
{cout << t << " ";
}template <class ...Args>
void ShowList(Args... args)
{int arr[] = { (PrintArg(args),0)... };cout << endl;
}int main()
{ShowList('x');ShowList('x', 'y');ShowList(1,'x', 'y');
}

也可以这样写:

template <class T>
int PrintArg(T t)
{cout << t << " ";return 0;
}template <class ...Args>
void ShowList(Args... args)
{int arr[] = { PrintArg(args)... };cout << endl;
}int main()
{ShowList('x');ShowList('x', 'y');ShowList(1,'x', 'y');
}

实际编译器编译推演生成了一下代码

template <class T>
int PrintArg(T t)
{cout << t << " ";return 0;
}void ShowList(int a,char b,char c)
{int arr[] = { PrintArg(a),PrintArg(b),PrintArg(c)};cout << endl;
}int main()
{ShowList(1,'x', 'y');
}

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

在这里插入图片描述

在这里插入图片描述

template <class ...Args>
void emplace_back(Args ...args)
{//...
}

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

int main()
{list<bit::string> mylist;//没有区别string s1("1111");mylist.push_back(s1);mylist.emplace_back(s1);cout << endl;string s2("2222");mylist.push_back(move(s1));mylist.emplace_back(move(s2));//有区别cout << endl;//先构造临时对象 + 移动构造mylist.push_back("1111");//直接构造mylist.emplace_back("1111");
}

在这里插入图片描述

模拟实现emplace_back

#pragma once
#include <assert.h>#include <iostream>using namespace std;namespace hb
{template <class T>struct ListNode{ListNode<T>* _prev;ListNode<T>* _next;T _data;ListNode(const T& data = T()):_prev(nullptr), _next(nullptr), _data(data){}ListNode(T&& data):_prev(nullptr), _next(nullptr), _data(move(data)){}template <class ...Args>ListNode(Args&&... args): _prev(nullptr), _next(nullptr), _data(forward<Args>(args)...){}};template <class T,class Ref,class Ptr>struct ListIterator{typedef ListNode<T> Node;Node* _node;typedef ListIterator<T,Ref,Ptr> self;ListIterator(Node* node):_node(node){}self& operator++(){_node = _node->_next;return *this;}self operator++(int){self tmp(*this);_node = _node->_next;return tmp;}self& operator--(){_node = _node->_prev;return *this;}self operator--(int){self tmp(*this);_node = _node->_prev;return tmp;}Ref operator*(){return _node->_data;}bool operator!=(const self& node){return _node != node._node;}bool operator==(const self& node){return _node == node._node;}Ptr operator->(){return &_node->_data;}};template <class T>struct ListConstIterator{typedef ListNode<T> Node;Node* _node;typedef ListConstIterator<T> self;ListConstIterator(Node* node):_node(node){}self& operator++(){_node = _node->_next;return *this;}self operator++(int){self tmp(*this);_node = _node->_next;return tmp;}self& operator--(){_node = _node->_prev;return *this;}self operator--(int){self tmp(*this);_node = _node->_prev;return tmp;}const T& operator*(){return _node->_data;}bool operator!=(const self& node){return _node != node._node;}bool operator==(const self& node){return _node == node._node;}const T* operator->(){return &_node->_data;}};template <class T>class list{typedef ListNode<T> Node;public:typedef ListIterator<T,T&,T*> iterator;typedef ListIterator<T,const T&,const T*> const_iterator;//typedef ListConstIterator<T> const_iterator;iterator begin(){return iterator(_head->_next);}const_iterator begin() const{return const_iterator(_head->_next);}iterator end(){return iterator(_head);}const_iterator end() const{return const_iterator(_head);}void empty_list(){_head = new Node;_head->_prev = _head;_head->_next = _head;}list(){empty_list();}~list(){clear();delete _head;_head = nullptr;}void clear(){iterator it = begin();while (it != end()){//it = erase(it);erase(it++);}}/*list(const list<T>& lt){empty_list();for (const auto& e : lt){push_back(e);}}*/void swap(list<T>& tmp){std::swap(_head, tmp._head);}template <class Iterator>list(Iterator first, Iterator last){empty_list();//不加会出问题while (first != last){push_back(*first);++first;}}list(const list<T>& lt){empty_list();list<T> tmp(lt.begin(), lt.end());swap(tmp);}list<T>& operator=(list<T> tmp){swap(tmp);return *this;}void push_back(const T& x){/*Node* tail = _head->_prev;Node* newnode = new Node(x);newnode->_prev = tail;newnode->_next = _head;tail->_next = newnode;_head->_prev = newnode;*/insert(end(),x);}void push_back(T&& x){/*Node* tail = _head->_prev;Node* newnode = new Node(x);newnode->_prev = tail;newnode->_next = _head;tail->_next = newnode;_head->_prev = newnode;*/insert(end(), move(x));}template <class ...Args>void emplace_back(Args&& ...args){insert(end(), forward<Args>(args)...);}void push_front(const T& x){insert(begin(),x);}void pop_back(){erase(--end());}void pop_front(){erase(begin());}iterator insert(iterator pos, const T& x){Node* node = pos._node;Node* prev = node->_prev;Node* newnode = new Node(x);newnode->_prev = prev;newnode->_next = node;prev->_next = newnode;node->_prev = newnode;return iterator(newnode);}template<class ...Args>iterator insert(iterator pos, Args&&... args){Node* node = pos._node;Node* prev = node->_prev;Node* newnode = new Node(forward<Args>(args)...);newnode->_prev = prev;newnode->_next = node;prev->_next = newnode;node->_prev = newnode;return iterator(newnode);}iterator insert(iterator pos, T&& x){Node* node = pos._node;Node* prev = node->_prev;Node* newnode = new Node(move(x));newnode->_prev = prev;newnode->_next = node;prev->_next = newnode;node->_prev = newnode;return iterator(newnode);}iterator erase(iterator pos){assert(pos != end());Node* del = pos._node;Node* prev = del->_prev;Node* next = del->_next;prev->_next = next;next->_prev = prev;return iterator(next);}bool empty() const{return _head == _head->_next;}T& front(){return _head->_next->_data;}const T& front() const{return _head->_next->_data;}T& back(){return _head->_prev->_data;}const T& back() const{return _head->_prev->_data;}size_t size() const{size_t count = 0;Node* pcur = _head->_next;while (pcur != _head){count++;pcur = pcur->_next;}return count;}void resize(size_t newsize, const T& data = T()){size_t oldsize = size();if (newsize <= oldsize){while (newsize != oldsize){pop_back();oldsize--;}}else{while (oldsize != newsize){push_back(data);oldsize++;}}}private:Node* _head;};
}

代码测试:

int main()
{hb::list<string> mylist;//没有区别string s1("1111");mylist.push_back(s1);mylist.emplace_back(s1);cout << endl;string s2("2222");mylist.push_back(move(s1));mylist.emplace_back(move(s2));//有区别cout << endl;//先构造临时对象 + 移动构造mylist.push_back("1111");//直接构造mylist.emplace_back("1111");
}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

相关文章:

C++新增的类功能和可变参数模板

C新增的类功能和可变参数模板 新的类功能默认成员函数 可变参数模板模拟实现emplace_back &#x1f30f;个人博客主页&#xff1a; 个人主页 新的类功能 默认成员函数 原来C类中&#xff0c;有6个默认成员函数&#xff1a; 构造函数析构函数拷贝构造函数拷贝赋值重载取地址…...

redo log 日志 与 undo log 日志工作原理

目录标题 1. redo log 日志2. undo log 日志3.总结 1. redo log 日志 redo log日志是 MySQL 数据中的重要日志之一&#xff0c;其本质是物理日志&#xff0c;存放于 数据库的数据目录中 &#xff0c;名称为&#xff1a; ib_logfile 。它的功能主要是用于存放脏数据的日志&…...

go语言结构体与json数据相互转换

本博文简要介绍go语言结构体如何与json格式化字符串相互转换。 文章目录 go语言结构体转换为json数据json数据转换为go结构体 go语言结构体转换为json数据 type Person struct {Name string json:"name"Age int json:"age"Hobbies []strin…...

jenkins 自动化部署Springboot 项目

一、安装docker 1.更新yum命令 yum -y update2.查看机器有残留的docker服务&#xff0c;有就卸载干净 查看docker 服务 rpm -qa |grep docker卸载docker sudo yum remove docker-ce docker-ce-cli containerd.io sudo rm -rf /var/lib/docker sudo rm -rf /var/lib/contai…...

使用xml发送国际短信(smspro)【吉尔吉斯斯坦】

//使用xml格式发送国外短信验证码【吉尔吉斯斯坦】官网&#xff1a;https://smspro.nikita.kg/ public function api_test($data,$user){$url "http://smspro.nikita.kg/api/message";$code 123456 ;$content Your verification code 123456, this verification …...

springmvc-springsecurity-redhat keycloak SAML2 xml实现

环境准备&#xff1a; jdk17 redhat keycloak 24 spring security 6 参照文档&#xff1a; 红帽KeyCloak&#xff1a;Red Hat build of Keycloak | Red Hat Product Documentation 入门指南&#xff1a;入门指南 | Red Hat Product Documentation 服务器管理指南&#x…...

【K8S系列】Kubernetes Pod节点CrashLoopBackOff 状态及解决方案详解【已解决】

在 Kubernetes 中&#xff0c;Pod 的状态为 CrashLoopBackOff 表示某个容器在启动后崩溃&#xff0c;Kubernetes 尝试重启该容器&#xff0c;但由于持续崩溃&#xff0c;重启的间隔时间逐渐增加。下面将详细介绍 CrashLoopBackOff 状态的原因、解决方案及相关命令的输出解释。 …...

Linux: Shell编程入门

Shell 编程入门 1 ) Shell 概念 shell 是 在英语中 壳, 外壳的意思可以把它想象成嵌入在linux这样的操作系统里面的一个微型的编程语言不像C语言, C 或 Java 等编程语言那么完整&#xff0c;它可以帮我们完成很多自动化任务例如保存数据监测系统的负载等等&#xff0c;我们同样…...

python爬虫实战案例——抓取B站视频,不同清晰度抓取,实现音视频合并,超详细!(内含完整代码)

文章目录 1、任务目标2、网页分析3、代码编写 1、任务目标 目标网站&#xff1a;B站视频&#xff08;https://www.bilibili.com/video/BV1se41117WP/?vd_sourcee8e376ccbc5aa4cfd88e6a7917adfd1a&#xff09;&#xff0c;用于本文测验 要求&#xff1a;抓取该网址下的视频&…...

容灾与云计算概念

​​​​​​基础知识容灾备份——备份技术系统架构与备份网络方案-CSDN博客 SAN&#xff0c;是storage area network的简称&#xff0c;翻译过来就是存储区域网络。 顾名思义&#xff0c;SAN首先是一个网络&#xff0c;其次它是关于存储的&#xff0c;区域则是指服务器和存储资…...

基于 Python 的自然语言处理系列(44):Summarization(文本摘要)

在这一部分中&#xff0c;我们将探讨如何使用 Transformer 模型将长文档压缩为摘要&#xff0c;这个任务被称为文本摘要。文本摘要是 NLP 领域中最具挑战性的任务之一&#xff0c;因为它需要理解长篇文本并生成连贯的总结&#xff0c;捕捉文档中的核心主题。然而&#xff0c;当…...

RabbitMQ安装部署

安装Erlang 由于RabbitMQ是用Erlang语言编写的&#xff0c;所以在安装RabbitMQ之前需要安装Erlang 安装依赖 [rootpro-ex ~]yum install make gcc gcc-c build-essential openssl openssl-devel unixODBC unixODBC-devel kernel-devel m4 ncurses-devel设置Eralng的存储库 […...

智联招聘×Milvus:向量召回技术提升招聘匹配效率

01. 业务背景 在智联招聘平台&#xff0c;求职者和招聘者之间的高效匹配至关重要。招聘者可以发布职位寻找合适的人才&#xff0c;求职者则通过上传简历寻找合适的工作。在这种复杂的场景中&#xff0c;我们的核心目标是为双方提供精准的匹配结果。在搜索推荐场景下&#xff0c…...

unplugin-auto-import 库作用

unplugin-auto-import是一个 Vite、Webpack 和 Rollup 的插件。 一、自动导入模块 1. 减少手动导入 在 JavaScript 和 TypeScript 项目中&#xff0c;它可以自动检测并导入常用的模块和函数&#xff0c;无需手动在每个文件中进行导入操作。这大大减少了代码中的重复性导入语…...

【Multisim14.0正弦波>方波>三角波】2022-6-8

缘由有没有人会做啊Multisim14.0-其他-CSDN问答参考方波、三角波、正弦波信号产生 - 豆丁网...

vue3纯前端验证码示例

前言 验证码的用途&#xff1a;通过要求用户输入一串难以被机器自动识别的字符或图像&#xff0c;有效阻止恶意用户或脚本通过暴力破解方式尝试登录账户。验证码的分类&#xff1a;常见的验证码有短信、文本、图形等&#xff0c;安全度越高&#xff0c;依赖的插件或服务也越多…...

招聘程序员

全栈总监❤️golang❤️UI设计师 ☀️前端☀️Nodejs工☀️平面设计☀️PHP工 ☀️安卓❤️Flutter❤️运维☀️爬虫 公司福利&#xff1a; ☃️ 带薪年假、年终奖、13k-18k薪 &#x1f3e9; 内宿 2人/间或外宿可补助 &#x1f4b5; 转正绩效 ✨节日礼金&#xff1a;生日礼金…...

Android 判断手机放置的方向

#1024程序员节&#xff5c;征文# 文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 需求 老板&#xff1a;我有个手持终端&#xff0c;不能让他倒了&#xff0c;当他倒或者倾斜的时候要发出报警&#xff1b; 程序猿&#xff1a;我这..... 老板…...

Telegram机器人的手机部署

目的 一直有读 epub 电子书的习惯&#xff0c;摘录段落复制下来段落很难看&#xff0c;把自己写的排版器的逻辑复制下来&#xff0c;写成了一个排版机器人所有发给机器人的文字&#xff0c;都会经过排版&#xff0c;后转发到读书频道 前提 本来最好方法是直接把机器人架在服…...

ffmpeg视频滤镜: 色温- colortemperature

滤镜简述 colortemperature 官网链接 》 FFmpeg Filters Documentation 这个滤镜可以调节图片的色温&#xff0c;色温值越大显得越冷&#xff0c;可以参考一下下图&#xff1a; 咱们装修的时候可能会用到&#xff0c;比如选择灯还有地板的颜色的时候&#xff0c;选暖色调还是…...

基于服务器使用 apt 安装、配置 Nginx

&#x1f9fe; 一、查看可安装的 Nginx 版本 首先&#xff0c;你可以运行以下命令查看可用版本&#xff1a; apt-cache madison nginx-core输出示例&#xff1a; nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

大数据学习(132)-HIve数据分析

​​​​&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能

1. 开发环境准备 ​​安装DevEco Studio 3.1​​&#xff1a; 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK ​​项目配置​​&#xff1a; // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...

系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文通过代码驱动的方式&#xff0c;系统讲解PyTorch核心概念和实战技巧&#xff0c;涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...

数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !

我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...

消息队列系统设计与实践全解析

文章目录 &#x1f680; 消息队列系统设计与实践全解析&#x1f50d; 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡&#x1f4a1; 权衡决策框架 1.3 运维复杂度评估&#x1f527; 运维成本降低策略 &#x1f3d7;️ 二、典型架构设计2.1 分布式事务最终一致…...