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

C++11相较于C++98的新特性介绍:列表初始化,右值引用与移动语义

一,列表初始化

1.1C++98中传统的{}

C++98中一般数组和结构体可以使用{}进行初始化:

struct Date
{int _year;int _month;int _day;
};int main()
{int a[] = { 1,2,3,4,5 };Date _date = { 2025,2,27 };return 0;
}

 1.2C++11中的{}

  1. C++11以后想统一初始化方式,试图实现一切对象皆可用{}初始化,{}初始化也叫做列表初始化。 
  2. 内置类型支持,自定义类型也支持,自定义类型本质是类型转换,中间会产生临时对象,最后优化了以后变成直接构造。 
  3. {}初始化的过程中,可以省略掉=。 
  4. C++11列表初始化的本意是想实现一个大统一的初始化方式,其次他在有些场景下带来的不少便利,如容器push/inset多参数构造的对象时,{}初始化会方便许多。
class Date
{
public:Date(int year = 1, int month = 1, int day = 1):_year(year), _month(month), _day(day){cout << "Date(int year, int month, int day)" << endl;}Date(const Date& d):_year(d._year), _month(d._month), _day(d._day){cout << "Date(const Date& d)" << endl;}
private:int _year;int _month;int _day;
};int main()
{int a[] = { 1,2,3,4,5 };Date _date = { 2025,2,27 };const Date& d2 = { 2027,2,29 };//右边{2027,2,29}是一个临时对象,需要加上const//也可以不加括号Date d3{ 2028,2,27 };//非{}初始化必须要加上等号Date d4 2025;//编译器报错Date d5 = 2025;return 0;
}

1.3C++11中的std::initializer_list 

        上面的{}初始化已然很方便,但是如果说我们要初始化像vector这样的对像时,他的参数个数是会发生变化的,显然仅仅只有上面的{}远远无法满足这种需求。所以c++中就提供了std::initializer_list的类, auto il = { 10, 20, 30 }; // thetype of il is an initializer_list ,这个类的本质是底层开一个数组,将数据拷贝过来,std::initializer_list内部有两个指针分别指向数组的开始和结束。

这是他的文档:initializer_list - C++ Reference,std::initializer_list支持迭代器遍历。 

区别是{}还是initializer_list的方法也很简单,{}传入的值个数是固定的,由需要初始化的对象类型决定,里面所有数据的类型可能不同。后者可写入的值不固定,但类型一定相同。

map<int, string> m{ {1,string("hallo")} };
vector<string> v{ "a","b","c" };

二,右值引用与移动语义 

我们之前学习的是C++98中的引用,比如原本有一个int类型的对象x,那么int& b = x,此时b其实就是x的别名。C++11之后,我们之前学过的这种引用方式被叫做左值引用。需要注意的是,无论是左值引用还是右值引用,本质上都是取别名。 

2.1左值与右值 

左值是一个表示数据的表达式(如变量名或解引用的指针),一般是有持久状态,存储在内存中,我
们可以获取它的地址
,左值可以出现赋值符号的左边,也可以出现在赋值符号右边。定义时const
修饰符后的左值,不能给他赋值,但是可以取它的地址。

右值也是一个表示数据的表达式,要么是字面值常量、要么是表达式求值过程中创建的临时对象
等,右值可以出现在赋值符号的右边,但是不能出现出现在赋值符号的左边,右值不能取地址。 

值得一提的是,左值的英文简写为lvalue,右值的英文简写为rvalue。传统认为它们分别是left
value、right value 的缩写。现代C++中,lvalue 被解释为loactor value的缩写,可意为存储在内
存中、有明确存储地址可以取地址的对象,而 rvalue 被解释为 read value,指的是那些可以提供
数据值,但是不可以寻址,例如:临时变量,字面量常量,存储于寄存器中的变量等,也就是说左
值和右值的核心区别就是能否取地址。

//常见的左值比如:
int p;
const int p1;
int a[10];
char c;
a[0] = 1;
string s("111111111");
s[0] = 'b';//....
//它们都有一个共同的特性:可以取地址//常见的右值比如:
10;
s[0] + a[0];
string("111111111111111");
min(s[0],a[0]);
//它们均是临时对象,无法取地址

2.2左值引用与右值引用 

Type& x = y;//左值引用
Type&& x = y;//右值引用

同样,右值引用其实就是给右值取别名。

1.对于左值引用,不可以直接引用右值,引用右值时需要加上const。

int& x = 10;//error
const int& x = 10;//true

2.对于右值引用,当然也不可以直接引用左值,但是可以引用move移动之后的左值。

int x = 10;
int&& y = x;//error
int&& y = std::move(x);//true
//move可以将左值强制类型转化为右值,是库里面的一个函数模板,本质内部是进行强制类型转换,当然他还涉
//及一些引用折叠的知识,我们后面会详细介绍。

3.需要注意的是变量表达式都是左值属性,也就意味着一个右值被右值引用绑定后,右值引用变量变量表达式的属性是左值。

int&& y = 10;//y此时是一个左值

4.语法层面看,左值引用和右值引用都是取别名,不开空间。从汇编底层的角度看无论左值引用还是右值引用,底层都是用指针实现的,没有本质区别。

2.3引用改变生命周期 

右值引用和带有const的左值引用都可以延长临时变量的声明周期,但后者无法被修改。

std::string s1 = "1111111111";
std::string&& s2 = s1 + s1;
const std::string& s3 = s1 + s1;s2 += "Text";//true
s3 += "Text";//error

 2.4左右值引用的参数匹配

在C++98中,实现一个const左值引用作为参数的函数,传入左值还是右值都可以匹配 

void f(int& x)
{std::cout << "f函数的左值引用重载(" << x << ")" << std::endl;
}void f(const int& x)
{std::cout << "f函数的const左值引用重载(" << x << ")" << std::endl;
}int main()
{int x = 10;f(x);f(10 + 20);return 0;
}

C++11中,对右值进行了明确定义,此时便可以分担const左值引用对于右值的引用任务给右值引用。即实参是左值会匹配f(左值引用),实参是const左值会匹配f(const 左值引用),实参是右值会匹配f(右值引用)。 (当然没有右值引用的重载下还可以通过const左值引用来引用右值)。

void f(int& x)
{std::cout << "f函数的左值引用重载(" << x << ")" << std::endl;
}void f(const int& x)
{std::cout << "f函数的const左值引用重载(" << x << ")" << std::endl;
}void f(int&& x)
{std::cout << "f函数的右值引用重载(" << x << ")" << std::endl;
}int main()
{int x = 10;const int y = 20;f(x);f(y);f(10 + 20);return 0;
}

2.5右值引用和移动语义的使用场景 

2.5.1移动构造与移动赋值 

  1. 1.移动构造函数是一种构造函数,类似拷贝构造函数,移动构造函数要求第一个参数是该类类型的引用,但是不同的是要求这个参数是右值引用,如果还有其他参数,额外的参数必须有缺省值。
  2. 2.移动赋值是一个赋值运算符的重载,他跟拷贝赋值构成函数重载,类似拷贝赋值函数,移动赋值函数要求第一个参数是该类类型的引用,但是不同的是要求这个参数是右值引用。
  3. 3.对于像string/vector这样的深拷贝的类或者包含深拷贝的成员变量的类,移动构造和移动赋值有意义,因为移动构造和移动赋值的第一个参数都是右值引用的类型,他的本质是要“窃取”引用的右值对象的资源,而不是像拷贝构造和拷贝赋值那样去拷贝资源,从提高效率。下面ELY::string例实现了移动构造和移动赋值,我们需要结合场景理解。

之前文章中我们自己实现的string类:

namespace ELY
{class string{public:typedef char* iterator;typedef const char* const_iterator;iterator begin(){return _str;}iterator end(){return _str + _size;}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);}void swap(string& s){::swap(_str, s._str);::swap(_size, s._size);::swap(_capacity, s._capacity);}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){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(){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){push_back(ch);return *this;}const char* c_str() const{return _str;}size_t size() const{return _size;}private:char* _str = nullptr;size_t _size = 0;size_t _capacity = 0;};
}

2.5.2右值引用和移动语义解决传值返回问题

我们知道,在函数传参的时候使用左值引用能够减少拷贝,比如下面通过字符串实现高精度计算的函数:

string AddStrings(string& num1, string& num2) {//原本不加引用时需要拷贝代价巨大string str;int end1 = num1.size() - 1, end2 = num2.size() - 1;// 进位int next = 0;while (end1 >= 0 || end2 >= 0){int val1 = end1 >= 0 ? num1[end1--] - '0' : 0;int val2 = end2 >= 0 ? num2[end2--] - '0' : 0;int ret = val1 + val2 + next;next = ret / 10;ret = ret % 10;str += ('0' + ret);}if (next == 1)str += '1';reverse(str.begin(), str.end());return str;
}int main()
{std::string s1 = "11111";std::string s2 = "22222";std::string s3 = AddStrings(s1, s2);std::cout << s3 << std::endl;return 0;
}

但是此时返回str时,如果str过大,那么s3在接收的时候会进行两次拷贝构造(在string没有实现移动构造以及编译器没有进行编译优化的前提下):

这样子代价特别巨大,但是有了上面的右值引用之后。因为右值是一个临时对象,我们完全可以走移动构造来完成上面的拷贝构造过程。直接把临时对象中的资源给抢过来。但是我们不能说将上面AddString的返回值改为string&&,因为str中存储的资源生命周期在函数的作用域内。无法达到预期效果,我们只有对string类实现了移动构造才能实现抢过来的那一步:

当我们把移动构造屏蔽后,s3接收str会经历以下过程,走了两次拷贝构造,等于说进行两次新的资源构建:

但是我们实现移动构造之后,全程只有移动构造,没有任何新资源的构建,极大节省了资源消耗:

2.5.3右值引用与移动语义在传参中的提效

  1. 查看STL文档我们发现C++11以后容器的push和insert系列的接口否增加的右值引用版本。
  2. 当实参是一个左值时,容器内部继续调用拷贝构造进行拷贝,将对象拷贝到容器空间中的对象。
  3. 当实参是一个右值,容器内部则调用移动构造,将实参的资源直接掠夺过来构造当前对象

测试代码:

int main()
{std::list<bit::string> lt;bit::string s1("111111111111111111111");lt.push_back(s1);cout << "*************************" << endl;lt.push_back(bit::string("22222222222222222222222222222"));cout << "*************************" << endl;lt.push_back("3333333333333333333333333333");cout << "*************************" << endl;lt.push_back(move(s1));cout << "*************************" << endl;return 0;
}

运行结果:

2.6类型分类(了解)

  1. C++11以后,进一步对类型进行了划分,右值被划分纯右值(pure value,简称prvalue)和将亡值(expiring value,简称xvalue)。
  2. 纯右值是指那些字面值常量或求值结果相当于字面值或是一个不具名的临时对象。如: 42、true、nullptr 或者类似str.substr(1, 2)、str1 + str2 传值返回函数调用,或者整形a、b、a++,a+b 等。纯右值和将亡值C++11中提出的,C++11中的纯右值概念划分等价于C++98中的右值。
  3. 将亡值是指返回右值引用的函数的调用表达式和转换为右值引用的转换函数的调用表达,如move(x)、static_cast<X&&>(x)。
  4. 泛左值(generalized value,简称glvalue),泛左值包含将亡值和左值。
  5. 有名字,就是glvalue;有名字,且不能被move,就是lvalue;有名字,且可以被move,就是xvalu;没有名字,且可以被移动,则是prvalue。 

官方文档:

值类别 - cppreference.com ,​​​​https://en.cppreference.com/w/cpp/language/value_category

2.7引用折叠

1.C++中不能直接定义引用的引用如int& && r = i; 这样写会直接报错,通过模板或 typedef
中的类型操作可以构成引用的引用。

using lref = int&;
using rref = int&&;int main()
{int y = 10;int& &&r = y;//errorlref&& z = y;//truereturn 0;
}

2.对于两种引用的四种组合,只有&& 与 && 组合时才是右值引用:

lref& x = y;//x类型是int&
lref&& x = y;//x类型是int&
rref& x = y;//x类型是int&
rref&& x = 10;//x类型是int&&
template<class T>
void f1(T& x)
{}template<class T>
void f2(T&& x)
{}
int main()
{int n = 0;//无折叠->类型实例化为int&f1<int>(n);f1<int>(0);//报错//折叠->类型实例化为int&f1<int&>(n);f1<int&>(0);//报错//折叠->类型实例化为int&f1<int&&>(n);f1<int&&>(0);//报错//折叠->示例化为const int&f1<const int&>(n);f1<const int&>(0);//折叠->实例化为const int&f1<const int&&>(n);f1<const int&&>(0);//无折叠->类型实例化为int&&f2<int>(n);//报错f2<int>(0);//折叠->类型实例化为int&f2<int&>(n);f2<int&>(0);//报错//折叠->类型实例化为int&&f2<int&&>(n);//报错f2<int&&>(0);//折叠->示例化为const int&f2<const int&>(n);f2<const int&>(0);//折叠->实例化为const int&&f2<const int&&>(n);//报错f2<const int&&>(0);return 0;
}
template<class T>
void Function(T&& t)
{int a = 0;T x = a;x++;cout << &a << endl;cout << &x << endl << endl;
}int main()
{//无折叠-模板类型实例化为int&&Function(10);//右值int a = 0;//折叠,因为a为左值,模板类型实例化为int&Function(a);//左值// std::move(a)是右值,推导出T为int,模板实例化为void Function(int&& t)Function(std::move(a)); // 右值const int b = 8;// b是左值,推导出T为const int&,引用折叠,模板实例化为void Function(const int&// 所以Function内部会编译报错,x不能++Function(b); // const 左值// std::move(b)右值,推导出T为const int,模板实例化为void Function(const int&&t)// 所以Function内部会编译报错,x不能++Function(std::move(b)); // const 右值return 0;
}

我们也称Function(T&& t)这种为万能引用,传左值为左值,而传右值则为右值。 

2.8完美转发

我们在实际过程中,可能在函数中再去调用别的函数,比如如下这种情况:

void f1(int& x)
{}void f1(int&& x)
{}template<class T>
void fc(T&& t)
{f1(t);
}
int main()
{int n = 0;fc(n);fc(0);return 0;
}

我们上面也说过,对于int&& x = y;此时的x为左值属性。我们发现对于上图中的两次fc调用,n是左值直到传到f1时也可以保持其左值属性不变。但0在传入fc之后,0是一个右值,一个右值被右值引用绑定后,右值引用变量表达式的属性是左值,也就是说fc函数中t的属性是左值。此时便会调用f1的左值引用版本,换言之0在函数传递中失去了其本身的右值属性。如果我们想要保持0自身的右值属性在传递中不丢失,就需要使用完美转发。

完美转发:

template <class _Ty>
_Ty&& forward(remove_reference_t<_Ty>& _Arg) noexcept
{ // forward an lvalue as either an lvalue or an rvaluereturn static_cast<_Ty&&>(_Arg);
}

完美转发forward本质是一个函数模板,他主要还是通过引用折叠的方式实现。此时我们只需要将上面的代码改为如下格式:

void f1(int& x)
{}void f1(int&& x)
{}template<class T>
void fc(T&& t)
{f1(forward<T>(t));
}
int main()
{int n = 0;fc(n);fc(0);return 0;
}

这样0在经fc传入f1时便会调用右值引用版本的重载。保留了其本身的右值属性。 

相关文章:

C++11相较于C++98的新特性介绍:列表初始化,右值引用与移动语义

一&#xff0c;列表初始化 1.1C98中传统的{} C98中一般数组和结构体可以使用{}进行初始化&#xff1a; struct Date {int _year;int _month;int _day; };int main() {int a[] { 1,2,3,4,5 };Date _date { 2025,2,27 };return 0; } 1.2C11中的{} C11以后想统一初始化方式&…...

ISIS(中间系统到中间系统)——基础

ISIS是一项通用的动态路由协议&#xff0c;其隶属于链路状态路由协议&#xff0c;最初运行与OSI七层的网络层&#xff0c;采用组播地址224.0.0.14和224.0.0.15两个组波段&#xff0c;由于其较高的拓展性与高速收敛&#xff0c;被大多数运营商网络所使用 起源 ISIS最初是由国际…...

如何使用useContext进行全局状态管理?

在 React 中&#xff0c;使用 useContext 进行全局状态管理是一种有效的方法&#xff0c;尤其在需要在多个组件之间共享状态时。useContext 允许你在组件树中传递数据&#xff0c;而无需通过每个组件的 props 逐层传递。以下是关于如何使用 useContext 进行全局状态管理的详细指…...

docker容器网络配置及常用操作

Linux内核实现名称空间的创建 ip netns&#xff08;网络名称空间&#xff09;命令 可以借助ip netns命令来完成对 Network Namespace 的各种操作。ip netns命令来自于iproute安装包&#xff0c;一般系统会默认安装&#xff0c;如果没有的话&#xff0c;请自行安装。 注意&am…...

GMII(Gigabit Media Independent Interface)详解

一、GMII的定义与作用 GMII&#xff08;千兆介质无关接口&#xff09;是用于千兆以太网&#xff08;1Gbps&#xff09;的标准化接口&#xff0c;连接 MAC层&#xff08;数据链路层&#xff09;与 PHY芯片&#xff08;物理层&#xff09;。其核心目标是支持高速数据传输&#x…...

Wireshark Lua 插件教程

本⽂主要介绍 Lua 脚本在 Wireshark 中的应⽤, Lua 脚本可以在 Wireshark 中完成如下功能: 从⽹络包中提取数据, 或者统计⼀些数据包(Dumper) 需要解析⼀种 Wireshark 不提供原⽣⽀持的协议(Dissector) ⽰例 协议解析 VREP 协议是 NOGD 框架对于 TRIP 协议的⼀种延伸和扩展…...

【多模态大模型】GLM-4-Voice端到端语音交互机器人VoiceAI

写在前面&#xff1a;开源选手中最能打的 GLM-4-Voice&#xff0c;由智谱 AI 和清华大学共同研发&#xff0c;并发表论文 “GLM-4-Voice: Towards Intelligent and Human-Like End-to-End Spoken Chatbot”&#xff0c;旨在打造智能且类人化的端到端语音聊天机器人。GLM-4-Voi…...

Unity 列表滚动到指定位置

使用场景 策划提出需求&#xff1a;当玩家打开领奖界面时&#xff0c;奖励列表需要自动滑动到可以领奖的奖励栏处或者正在进行的任务栏处。 思路 1、将Content设置好对齐方式和锚点 子物体的预制体和Content&#xff1a;pivot轴心点设置为(0,1),并且设置为左上角对齐。 2、主…...

使用Crawlee可破题js渲染采集数据

使用 Crawlee 实现自动化爬虫流程 1. Crawlee 简介 Crawlee 是一个强大的爬虫框架&#xff0c;用于快速构建和维护可靠的爬虫。它支持多种爬虫类型&#xff0c;包括基于 Cheerio 和 Playwright 的爬虫&#xff0c;能够高效处理静态和动态网页。 2. 项目目标 通过自动化脚本实…...

小红的字母游戏(A组)

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 题目描述 小红有一个长度为 nnn 的字符串 sss&#xff0c;仅包含小写字母&#xff0c;小红可以选出 kkk 个字符&#xff0c;组成一个新的字符串 ttt&#xff0c;对于 ttt 的每一个字符 tit_it…...

MFC线程

创建线程 HANDLE m_hThread; m_hThread CreateThread(NULL, 0, save_snapshot, (LPVOID)this, 0, &iThreadId);开启线程循环等待 DWORD WINAPI save_snapshot(LPVOID pVoid) {while (true){//持续循环等待事件到达。接收到事件信号后才进入if。if (::WaitForSingleObjec…...

目标检测YOLO实战应用案例100讲-面向无人机图像的小目标检测

目录 知识储备 YOLO v8无人机拍摄视角小目标检测 数据集结构 环境部署说明 安装依赖 模型训练权重和指标可视化展示 训练 YOLOv8 PyQt5 GUI 开发 主窗口代码 main_window.py 使用说明 无人机目标跟踪 一、目标跟踪的基本原理 二、常用的目标跟踪算法 基于YOLOv…...

【Java分布式】Nacos注册中心

Nacos注册中心 SpringCloudAlibaba 也推出了一个名为 Nacos 的注册中心&#xff0c;相比 Eureka 功能更加丰富&#xff0c;在国内受欢迎程度较高。 官网&#xff1a;https://nacos.io/zh-cn/ 集群 Nacos就将同一机房内的实例划分为一个集群&#xff0c;一个服务可以包含多个集…...

VSCode轻松调试运行.Net 8.0 Web API项目

1.背景 我一直都是用VS来开发.NetCore项目的&#xff0c;用的比较顺手&#xff0c;也习惯了。看其他技术文章有介绍VS Code更轻量&#xff0c;更方便。所以我专门花时间来使用VS Code&#xff0c;看看它是如何调试代码、如何运行.Net 8.0 WebAPI项目。这篇文章是一个记录的过程…...

PageHelper新发现

PageHelper 背景解决reasonablepageSizeZero 背景 今天发现了一个很有趣的现象&#xff0c;接手一个很老的项目springmvc项目、使用PageHelper分页实现常见的后端接口分页功能。但是发现当页码参数大于实际的页码数时、正常不应该返回数据&#xff0c;但是目前确一直返回数据不…...

python编写liunx服务器登陆自动巡检脚本

前言&#xff1a; 用户需要一份用Python编写的Linux系统巡检脚本&#xff0c;检查内存、磁盘、CPU使用率&#xff0c;还有网络连通性。 首先&#xff0c;我得确定用户的使用场景。可能用户是系统管理员&#xff0c;需要定期监控服务器状态&#xff0c;确保系统正常运行。 或者…...

基于 Flink CDC YAML 的 MySQL 到 Kafka 流式数据集成

本教程的演示都将在 Flink CDC CLI 中进行&#xff0c;无需一行 Java/Scala 代码&#xff0c;也无需安装 IDE。 这篇教程将展示如何基于 Flink CDC YAML 快速构建 MySQL 到 Kafka 的 Streaming ELT 作业&#xff0c;包含整库同步、表结构变更同步演示和关键参数介绍。 准备阶段…...

数据结构——并查集

AcWing - 算法基础课 Acwing——合并集合 代码如下&#xff1a; #include <bits/stdc.h>using namespace std; #define fs first #define sc second #define endl \n #define all(x) x.begin(), x.end() typedef long long ll; typedef pair<int, int> PII;cons…...

详细解析d3dx9_27.dll丢失怎么办?如何快速修复d3dx9_27.dll

运行程序时提示“d3dx9_27.dll文件缺失”&#xff0c;通常由DirectX组件损坏或文件丢失引起。此问题可通过系统化修复方法解决&#xff0c;无需重装系统或软件。下文将详细说明具体步骤及注意事项。 一.d3dx9_27.dll缺失问题的本质解析 当系统提示“d3dx9_27.dll丢失”时&…...

【STL】4.<list>

list 前言list容器一.list初始化二.常用函数三.排序 总结 前言 stl系列主要讲述有关stl的文章&#xff0c;使用STL可以大大提高程序开发的效率和代码的可维护性&#xff0c;且在算法比赛中&#xff0c;STL可以帮助我们更方便地实现各种算法。提高我们的效率。 list容器 要使用…...

小程序中头像昵称填写

官方文档 参考小程序用户头像昵称获取规则调整公告 新的小程序版本不能通过wx.getUserProfile和wx.getUserInfo获取用户信息 <van-field label"{{Avatar}}" label-class"field-label" right-icon-class"field-right-icon-class"input-class&…...

vLLM服务设置开机自启动(Linux)

要在开机时进入指定的 conda 环境并启动此 vllm 服务&#xff0c;您可以通过以下步骤设置一个 systemd 服务来自动执行脚本。 一、第一步&#xff1a;创建一个启动脚本 1.打开终端并创建启动脚本&#xff0c;例如 /home/username/start_vllm.sh&#xff08;请替换 username 为…...

Cherno 游戏引擎笔记(91~111)

好久不见&#xff01; 个人库的地址&#xff1a;&#xff08;GitHub - JJJJJJJustin/Nut: The game_engine which learned from Cherno&#xff09;&#xff0c;可以看到我及时更新的结果。 -------------------------------Saving & Loading scene-----------------------…...

面试八股文--数据库基础知识总结(1)

1、数据库的定义 数据库&#xff08;DataBase&#xff0c;DB&#xff09;简单来说就是数据的集合数据库管理系统&#xff08;Database Management System&#xff0c;DBMS&#xff09;是一种操纵和管理数据库的大型软件&#xff0c;通常用于建立、使用和维护数据库。数据库系统…...

算法系列之动态规划

动态规划&#xff08;Dynamic Programming&#xff0c;简称DP&#xff09;是一种用于解决复杂问题的算法设计技术。它通过将问题分解为更小的子问题&#xff0c;并存储这些子问题的解来避免重复计算&#xff0c;从而提高算法的效率。本文将介绍动态规划的基本概念、适用场景、复…...

网站漏洞安全测试 具体渗透思路分析

渗透测试这些是经常谈到的问题了&#xff0c;我觉得当有了渗透接口测试之后你就会发现渗透测试这一方面也就是&#xff1a;1.基本漏洞测试&#xff1b;2.携带"低调"构思的心血来潮&#xff1b;3.锲而不舍的信念。我们在对网站&#xff0c;APP进行渗透测试的过程中会发…...

Spring Boot(七):Swagger 接口文档

1. Swagger 简介 1.1 Swagger 是什么&#xff1f; Swagger 是一款 RESTful 风格的接口文档在线自动生成 功能测试功能软件。Swagger 是一个规范和完整的框架&#xff0c;用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。目标是使客户端和文件系统作为服务器以同样的…...

【Mac电脑本地部署Deepseek-r1:详细教程与Openwebui配置指南】

文章目录 前言电脑配置&#xff1a;安装的Deepseek版本&#xff1a;使用的UI框架&#xff1a;体验效果展示&#xff1a;本地部署体验总结 部署过程Ollama部署拉取模型运行模型Openwebui部署运行Ollama服务在Openwebui中配置ollama的服务 后话 前言 deepseek最近火的一塌糊涂&a…...

测试的BUG分析

在了解BUG之前,我们要先了解软件测试的生命周期,因为大多数BUG都是在软件测试的过程中被发现的 软件测试的生命周期 在了解 软件测试的生命周期 之前,我们要先了解 软件的生命周期 ,虽然他们之间只差了两个字,但是差距还是很大的 首先是 软件生命周期 ,这个是站在 软件 的角…...

linux里面的过滤符号 | 是如何实现的

ls -l | grep ".txt" 的实现过程涉及无名管道的创建、进程的创建&#xff08;fork()&#xff09;以及输入输出的重定向&#xff08;dup2()&#xff09;。以下是详细的实现步骤和代码示例&#xff1a; 实现步骤 创建无名管道&#xff1a; 使用pipe()系统调用创建一个无…...

结构型模式--组合模式

概念 组合人模式是结构型设计模式的一种&#xff0c;主要是用于解决代码中出现类像树一样进行组合而出现的组合结构的相关操作问题。使其树中的任意一个节点&#xff08;无论是子节点还是父节点&#xff09;都可以使用同一套接口进行操作。 使用场景 1、如果希望我们对象组合…...

drupal可以自动将测试环境的网页部署到生产环境吗

在 Drupal 中&#xff0c;自动将测试环境的网页部署到生产环境通常是通过设置合适的开发和部署流程来实现的。这种自动化部署过程通常涉及以下几个步骤&#xff1a; 1. 版本控制&#xff08;Git&#xff09; 为了保证测试环境和生产环境的一致性&#xff0c;首先需要使用 Git…...

Android应用app实现AI电话机器人接打电话

Android应用app实现AI电话机器人接打电话 --安卓AI电话机器人 一、前言 【Dialer3.0智能拨号器】Android版手机app&#xff0c;由于采用蓝牙电话的方式来调用手机SIM卡发起呼叫、接听来电&#xff0c;并接收和处理通话的声音&#xff0c;通常我们以“蓝牙电话方案”来称呼它。 …...

【面试宝典】Java中创建线程池的几种方式以及区别

强烈推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站:人工智能 创建线程池有多种方式&#xff0c;主要通过 Java 的 java.util.concurrent 包提供的 Executors 工具类来实现。以下是几…...

【数据结构】哈希表

目录 哈希表 基本思想 基本原理 哈希表工作机制简化描述 关于查找、插入和删除 HashMap 主要成员变量 主要方法 内部实现细节 注意事项 哈希表 哈希表是一种基于哈希函数的数据结构&#xff0c;它通过键值对的形式存储数据&#xff0c;并允许通过键快速查找对应的值…...

MySQL 使用 `WHERE` 子句时 `COUNT(*)`、`COUNT(1)` 和 `COUNT(column)` 的区别解析

文章目录 1. COUNT() 函数的基本作用2. COUNT(*)、COUNT(1) 和 COUNT(column) 的详细对比2.1 COUNT(*) —— 统计所有符合条件的行2.2 COUNT(1) —— 统计所有符合条件的行2.3 COUNT(column) —— 统计某一列非 NULL 的记录数 3. 性能对比3.1 EXPLAIN 分析 4. 哪种方式更好&…...

RabbitMQ系列(一)架构解析

RabbitMQ 架构解析 RabbitMQ 是一个基于 AMQP 协议的开源消息中间件&#xff0c;其核心架构通过多组件协作实现高效、可靠的消息传递。以下是其核心组件与协作流程的详细说明&#xff1a; 一、核心组件与功能 Broker&#xff08;消息代理服务器&#xff09; RabbitMQ 服务端核…...

如何让传统制造企业从0到1实现数字化突破?

随着全球制造业不断向智能化、数字化转型&#xff0c;传统制造企业面临着前所未有的机遇与挑战。数字化转型不仅是技术的革新&#xff0c;更是管理、文化、业务流程等全方位的变革。从零开始&#xff0c;如何带领一家传统制造企业走向数字化突破&#xff0c;是许多企业领导者面…...

基于Spring Boot的二手物品交易平台设计与实现(LW+源码)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…...

释放 Cursor 的全部潜能:快速生成智能 Cursor Rules

释放 Cursor 的全部潜能&#xff1a;使用 PromptCoder 从 package.json 快速生成智能 Cursor Rules 我们将深入探讨如何利用您项目中的 package.json 文件&#xff0c;轻松生成 Cursor Rules&#xff0c;并通过 PromptCoder 这个强大的工具&#xff0c;快速创建高质量的 curso…...

C#高级:结合Linq的SelectMany方法实现笛卡尔积效果

一、笛卡尔积定义 又称直积&#xff0c;表示为X Y&#xff0c;第一个对象是X的成员而第二个对象是Y的所有可能有序对的其中一个成员 二、基础示例 class Program {static void Main(string[] args){try{List<List<string>> input new List<List<string&g…...

【洛谷入门赛】B4018 游戏与共同语言

题意 这里有两个队伍分别叫 A 和 B。 分别给定这两个队伍的胜利数、净胜局、平局数量。 求哪个队更厉害&#xff0c;就输出哪个。 具体比较规则如下&#xff1a; 两队中胜利数高的队伍更厉害。 若胜利数相同&#xff0c;净胜数高的队伍更厉害。 若净胜数仍然相同&#x…...

Python学习总结

客户端与服务端聊天窗口 服务端 导入 wxPython 用于创建图形界面。 socket 用于网络通信&#xff0c;AF_INET 是 IPv4 地址族&#xff0c;SOCK_STREAM 表示流式套接字&#xff08;TCP&#xff09;。 利用wxPython 创建图形界面&#xff0c;并通过 socket 与服务器通信。 主要…...

android系统_模拟ZygoteServer写一个socket通信

目录 一,模拟ZygoteServer 二,Client 代表app 三,输出结果 四,结束语 一,模拟ZygoteServer ZygoteServer&#xff0c;不断的监听来自客户端的请求 package org.study.tiger;import java.io.*; import java.net.*; import java.util.concurrent.*;import java.io.*; impor…...

LangChain教程 - RAG - PDF问答

系列文章索引 LangChain教程 - 系列文章 在现代自然语言处理&#xff08;NLP&#xff09;中&#xff0c;基于文档内容的问答系统变得愈发重要&#xff0c;尤其是当我们需要从大量文档中提取信息时。通过结合文档检索和生成模型&#xff08;如RAG&#xff0c;Retrieval-Augment…...

李代数(Lie Algebras)与Attention:深度学习中的数学之美

李代数与Attention&#xff1a;深度学习中的数学之美 引言 作为一名深度学习研究者&#xff0c;您一定对Transformer模型和其中的注意力机制&#xff08;Attention&#xff09;不陌生。Attention通过查询&#xff08;Query&#xff09;、键&#xff08;Key&#xff09;和值&a…...

docker本地镜像源搭建

最近Deepseek大火后&#xff0c;接到任务就是帮客户装Dify&#xff0c;每次都头大&#xff0c;因为docker源不能用&#xff0c;实在没办法&#xff0c;只好自己搭要给本地源。话不多说具体如下&#xff1a; 1、更改docker的配置文件&#xff0c;添加自己的私库地址&#xff0c…...

监督学习单模型—线性模型—LASSO回归、Ridge回归

目标变量通常有很多影响因素&#xff0c;通过各类影响因素构建对目标变量的回归模型&#xff0c;能够实现对目标的预测。但根据稀疏性的假设&#xff0c;即使影响一个变量的因素有很多&#xff0c;其关键因素永远只会是少数。在这种情况下&#xff0c;还用传统的线性回归方法来…...

StableDiffusion打包 项目迁移 项目分发 1

文章目录 SD项目迁移前置知识webui-user.batwebui.batlaunch_utils.py 下一篇开始实践 SD项目迁移 显卡驱动更新&#xff1a;https://www.nvidia.cn/geforce/drivers/ 下载安装三个程序&#xff1a; python3.10.6: https://www.python.org/downloads/release/python-3106/gi…...

【C++】模板初阶

文章目录 一. 泛型编程1.1 什么是模板1.2 为什么要使用模板 二. 函数模板2.1 函数模板概念2.2 函数模板格式2.3 函数模板的原理2.4 函数模板的实例化2.4.1 隐式实例化2.4.2 显式实例化 2.5 模板参数的匹配原则 三. 类模板3.1 类模板的定义格式3.2 类模板的实例化3.3 在类模板外…...