新闻详情

新闻详情

首页 / 资讯中心 / 详情

【C++进阶】C++ 11(中)

发布时间:2026/10/1 8:34:51来源:尧图网络
【C++进阶】C++ 11(中)
目录1 左值与右值2 左值引用与右值引用3 引用延长临时对象生命周期4 重载匹配5 移动构造 移动赋值6 值类别分类C117 引用折叠8 完美转发 std::forward1 左值与右值左值 (lvalue)可以取地址对象拥有持久存储内存实体可以出现在赋值号左边 / 右边。const修饰左值不能赋值但是依旧可以取地址。变量、解引用*p、数组元素s[0]都是左值。右值 (rvalue)不能取地址字面量常量、函数返回临时对象、表达式运算结果。只能出现在赋值符号右侧。如10、xy、fmin(a,b)、string(abc)临时对象。现代 C 概念 lvalue locator value有存储位置可以取地址 rvalue read value只读没有持久身份大多为临时。#includeiostream #includestring using namespace std; int main() { // 左值可以取地址 int* p new int(0); int b 1; const int c b; *p 10; string s(111111); s[0] x; cout c endl; cout (void*)s[0] endl; // 右值不能取地址 double x 1.1,y 2.2; 10; xy; fmin(x,y); string(11111); // cout 10; //编译报错右值不能取地址 return 0; }2 左值引用与右值引用Type左值引用绑定左值const Type可以绑定左值也可以绑定右值。Type右值引用绑定右值右值引用变量本身是左值std::move()不是移动只是强制类型转换把左值转成右值底层本质是static_castT。#includeiostream #includestring using namespace std; int main() { int b 10; int r1 b; // 左值引用绑定左值 int rr1 20; // 右值引用绑定右值 const int rx 30; // const左值引用可以绑定右值 // int rr2 b; //报错右值引用不能直接绑定左值 int rr2 move(b); // move将左值转为右值 // 重点rr1、rr2是变量表达式中属于左值 // int rr3 rr1; //报错rr1是左值 int rr3 move(rr1); return 0; }3 引用延长临时对象生命周期const T和T都可以延长临时对象生命周期const 引用不能修改对象非 const 右值引用可以修改临时对象。#includeiostream #includestring using namespace std; int main() { std::string s1 Test; // std::string r1 s1; //错误不能绑定左值 const std::string r2 s1 s1; // const左值引用延长临时对象 // r2 Test; // const不可修改 std::string r3 s1 s1; // 右值引用延长生命周期 r3 Test; // 可以修改 std::cout r3 \n; return 0; }4 重载匹配函数同时重载T/const T/T实参类型会匹配对应版本#includeiostream using namespace std; void f(int x) { std::cout 左值引用重载 f( x )\n; } void f(const int x) { std::cout const左值引用重载 f( x )\n; } void f(int x) { std::cout 右值引用重载 f( x )\n; } int main() { int i 1; const int ci 2; f(i); // f(int) f(ci); // f(const int) f(3); // f(int)没有右值版本会回落const左值引用 f(std::move(i)); // f(int) int x 1; // f(x); //x变量是左值调用f(int) f(std::move(x)); return 0; }5 移动构造 移动赋值适用场景管理堆内存资源的类string、vector。拷贝构造开辟新内存完整拷贝全部资源开销大。移动构造只窃取源对象内部资源指针不拷贝内存源对象置空效率极高。移动构造函数参数必须是该类型的右值引用移动赋值同理。模拟简易 bit::string 实现演示移动语义#define _CRT_SECURE_NO_WARNINGS #includeiostream #includeassert.h #includecstring #includealgorithm using namespace std; namespace bit { class string { public: typedef char* iterator; iterator begin(){return _str;} iterator end(){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) { std::swap(_str, s._str); std::swap(_size, s._size); std::swap(_capacity, s._capacity); } //拷贝构造 string(const string s) { cout string(const string s) -- 拷贝构造 endl; _size s._size; _capacity s._capacity; _str new char[_capacity 1]; strcpy(_str, s._str); } //移动构造参数是右值引用 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) { delete[] _str; _size s._size; _capacity s._capacity; _str new char[_capacity1]; strcpy(_str, s._str); } 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[n1]; if(_str) strcpy(tmp,_str); delete[] _str; _str tmp; _capacity n; } } void push_back(char ch) { if(_size _capacity) { size_t newcap _capacity 0 ? 4 : _capacity*2; reserve(newcap); } _str[_size] ch; _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; }; } int main() { bit::string s1(xxxxx); bit::string s2 s1; //拷贝构造 bit::string s3 bit::string(yyyyy); //临时对象移动构造编译器可优化消除 bit::string s4 move(s1); //移动构造 return 0; }返回局部对象场景函数返回局部对象局部对象是右值会触发移动构造编译器 RVO/NRVO 返回值优化可以直接消除拷贝 / 移动。 g 编译关闭优化g test.cpp -fno-elide-constructors可以看到完整移动 / 拷贝调用。容器接口也增加右值引用版本push_back(T val)传入临时对象会走移动避免深拷贝。右值引⽤和移动语义在传参中的提效6 值类别分类C11表达式分为两大分支glvalue 泛左值lvalue左值 xvalue将亡值 (expiring value)rvalue 右值xvalue将亡值 prvalue纯右值prvalue 纯右值字面量、运算表达式、传值返回的临时对象等价 C98 时代传统右值。xvalue 将亡值std::move(obj)转换之后的对象即将被销毁的资源对象。图解逻辑 expression ├─ glvalue 泛左值 │ ├─ lvalue 左值 │ └─ xvalue 将亡值 └─ rvalue 右值 ├─ xvalue 将亡值 └─ prvalue 纯右值7 引用折叠C 不允许直接手写int引用的引用但是模板、typedef 会间接生成引用的引用此时触发引用折叠规则T →TT →TT →TT →T总结只要存在左值引用折叠结果就是左值引用只有两个都是右值引用才得到右值引用。模板参数T叫做万能引用转发引用如果传入实参是左值T 推导为Type折叠之后形参变成Type左值引用如果传入实参是右值T 推导为Type形参变成Type右值引用。8 完美转发 std::forward问题万能引用接收参数参数变量本身是左值直接向下一层函数传递会丢失原来的值类别原本右值变成左值。std::forwardT(arg)保留实参原本的值类别左值继续作为左值右值继续作为右值向下传递。底层依靠引用折叠 static_cast 实现。小结区分左值右值看是否可以取地址右值引用变量本体属于左值。move 仅仅做强制类型转换不会移动资源移动构造 / 移动赋值才窃取资源。万能引用T依靠引用折叠变量是左值会丢失值类别需要forward完美转发。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Idea maven安装及卸载本地jar包的正确方法 2026/10/1 9:29:36

Idea maven安装及卸载本地jar包的正确方法

一、卸载本地jar包依赖;本地jar包位置:直接从本地仓库删除下面对应文件夹即可:无法从中央仓库下载依赖包;二、安装本地jar包依赖;打开cmd窗口,执行下面命令即可:mvn install:install-file -Dfil…

阅读更多 →
LangGraph4j多智能体Supervisor架构实践与踩坑 2026/10/1 9:29:36

LangGraph4j多智能体Supervisor架构实践与踩坑

前一阵子在做一个 Java 后端团队的技术调研报告生成助手,需求很朴素:用户丢一个技术主题,它负责查资料、抽数据、写报告。试了两周单智能体方案,终态效果总是不稳定——不是资料查全了但报告结构乱,就是报告漂亮但数据…

阅读更多 →
开源模拟赛车驾驶舱OpenRig:铝型材DIY搭建全指南 2026/10/1 9:29:36

开源模拟赛车驾驶舱OpenRig:铝型材DIY搭建全指南

老玩家都知道,模拟赛车这事儿一旦认真起来,最后都会走到同一个坑里:方向盘和踏板只是开始,真正决定体验的是“架子”。我花了小半年时间从零搭了一个开源模拟赛车驾驶舱,名字就叫 OpenRig。它不是一个商品,…

阅读更多 →
多模型协同智能体平台架构设计与安全策略编排实战 2026/10/1 9:29:36

多模型协同智能体平台架构设计与安全策略编排实战

这两年做AI应用踩过的最大一个坑,就是“多个模型一起用”。很多人以为把几个大模型API全接进来,做一个模型超市就行,结果真跑起来才发现:模型之间互相抢流量、回答风格不一致、权限边界模糊、调用链根本没法审计。我之前复盘过一个…

阅读更多 →
[Err] 1071 - Specified key was too long; max key length is 767 bytes,【各版本mysql均已解决】 2026/10/1 9:29:29

[Err] 1071 - Specified key was too long; max key length is 767 bytes,【各版本mysql均已解决】

[Err] 1709 - Index column size too large. The maximum column size is 767 bytes.错误信息如下所示:[SQL]CREATE TABLE permissions (role varchar(50) NOT NULL,resource varchar(512) NOT NULL,action varchar(8) NOT NULL,UNIQUE INDEX uk_role_permission (r…

阅读更多 →
用visual studio code打开vue项目,右键“在集成终端中打开”,“终端”页签一直显示“PS C:\> ”,无法定位到项目当前位置。 2026/10/1 9:29:29

用visual studio code打开vue项目,右键“在集成终端中打开”,“终端”页签一直显示“PS C:\> ”,无法定位到项目当前位置。

一、问题:vue项目用vscode打开,操作如下:二、解决方法:文件--》首选项--》设置;加入配置信息:"terminal.integrated.shell.windows": "C:\\Windows\\System32\\cmd.exe"另外&#xff1…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉