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

【C++】左值引用、右值引用

目录一、右值引用的意义二、基础理解左值与右值1. 左值LvalueLocator Value常见的左值场景2. 右值RvalueRead Value2.1 纯右值prvalue常见的纯右值场景2.2 将亡值xvalue常见的将亡值场景3. 左值与右值的核心区别三、右值引用的定义与语法规则1. 左值引用的回顾与局限2. 右值引用的语法与本质基础语法3. std::move ()做了什么4. 左值引用 vs 右值引用四、右值引用的两大核心应用场景1. 移动语义告别无意义的深拷贝实现资源高效转移1.1 无移动语义的痛点深拷贝的性能浪费1.2 基于右值引用实现移动语义1.3 移动语义的常见场景2. 完美转发2.1 完美转发的底层支撑2.1.1 万能引用转发引用2.1.2 引用折叠规则2.1.3 std::forward () 的作用2.2 完美转发的示例2.3 完美转发的常见场景五、高频踩坑点与实践建议1. 高频踩坑点坑 1std::move () 之后继续使用原对象坑 2对函数返回值使用 std::move ()坑 3误以为右值引用变量本身是右值坑 4给移动构造 / 移动赋值加 const 修饰坑 5把普通右值引用当成万能引用2. 实践建议一、右值引用的意义在 C 的编程世界中对象的拷贝与资源管理一直是性能优化的核心痛点。在 C11 标准之前我们编写的代码中隐藏着大量临时对象的深拷贝开销比如函数返回一个非引用类型的对象、容器插入临时对象时都会触发拷贝构造函数完成堆内存的重新分配与数据复制而临时对象在表达式结束后就会被销毁这就造成了完全无意义的内存操作与性能浪费。举个最简单的例子std::string str hello world;表达式会生成一个临时的 string 对象再通过拷贝构造把数据复制给 str随后临时对象被销毁。如果字符串很长这个深拷贝的开销是完全可以避免的。而 C11 引入的右值引用正是为了解决这个问题。它不仅重新定义了 C 的资源管理哲学让我们可以对即将销毁的临时对象的资源进行转移而非拷贝还支撑了泛型编程中的完美转发成为现代 C 不可或缺的核心特性。二、基础理解左值与右值1. 左值LvalueLocator Value左值的核心定义是可以通过取地址运算符获取其内存地址、拥有持久生命周期的表达式。简单来说左值就是一个 “有名字、有固定内存地址” 的对象你可以找到它的存储位置除了 const 修饰的左值外都可以修改其内容。左值既可以放在赋值号的左边也可以放在赋值号的右边作为右值使用。常见的左值场景普通变量、const 修饰的变量const 左值不可修改但依然可以取地址属于左值对指针解引用的结果*ptr数组的元素arr[index]结构体 / 类的非静态成员变量返回左值引用的函数调用前缀自增 / 自减表达式i、--iint main() { int i 0; i 1; // i是变量可修改左值能放在赋值号左侧 const int ci 5; // ci 6; // 报错const左值不可修改但ci可获取地址仍是左值 int* pi i; *pi 1; // *pi对指针解引用左值 int arr[5] {0}; arr[0] 1; // 数组元素左值 struct { int m_a; } st, *pst st; st.m_a 1; // 结构体成员左值 pst-m_a 2; return 0; }2. 右值RvalueRead ValueC11 之后右值被细分为纯右值prvaluePure Rvalue和将亡值xvalueeXpiring Value两类二者共同构成了右值。右值的核心定义是无法通过取地址、生命周期短暂的临时表达式结果它代表的是一个值而非值所在的存储位置。右值只能放在赋值号的右侧不能放在左侧。2.1 纯右值prvalue纯右值是 C98 标准中传统意义上的右值核心是 “字面量、临时计算结果”没有持久的存储地址。常见的纯右值场景除字符串字面量外的字面常量如42、a、true字符串字面量是 const char 数组类型属于左值算术、逻辑、关系运算符的求值结果如12、a10、ab非引用类型返回值的函数调用结果后置自增 / 自减表达式i、i--lambda 表达式2.2 将亡值xvalue将亡值是 C11 为了配合右值引用新增的概念核心是 “资源即将被转移、生命周期即将结束的对象”它是连接左值和右值的桥梁。将亡值虽然可以通过特殊方式获取地址但它的核心使命是完成资源转移使用后就会被销毁因此归属于右值范畴。常见的将亡值场景std::move()的返回结果返回右值引用类型的函数调用结果类型转换为右值引用的表达式结果int getNum() { return 100; } int main() { int i 0, c 0; i 42; // 字面值42纯右值 c a; // 字面值a纯右值 i 1 2; // 算术表达式结果纯右值 i (c ! a); // 逻辑表达式结果纯右值 i getNum(); // 非引用返回值纯右值 int rri std::move(i);// std::move(i)的结果将亡值右值 return 0; }3. 左值与右值的核心区别核心特性左值右值纯右值 将亡值内存地址可通过获取稳定的内存地址无法直接通过获取地址生命周期持久随变量 / 对象的作用域存在临时表达式结束后即销毁除非被引用绑定可修改性非 const 左值可修改const 左值不可修改不可直接修改赋值位置可放在赋值号左侧、右侧只能放在赋值号右侧引用绑定可被左值引用、const 左值引用绑定只能被 const 左值引用、右值引用绑定三、右值引用的定义与语法规则1. 左值引用的回顾与局限在 C11 之前我们使用的引用都是左值引用用符号声明本质是给变量起一个 “别名”底层通过指针实现必须在定义时初始化且初始化后无法重新绑定到其他对象。左值引用的核心局限非 const 左值引用只能绑定到左值无法绑定到右值。只有 const 左值引用是个例外它可以同时绑定左值和右值但 const 修饰决定了我们无法通过它修改绑定的对象。int main() { int a 10; int ra a; // 正确非const左值引用绑定左值 // int rb 10; // 报错非const左值引用无法绑定右值 const int rca a; // 正确const左值引用绑定左值 const int rcb 10; // 正确const左值引用绑定右值 // rcb 20; // 报错const引用无法修改绑定对象 return 0; }这个局限带来了两个核心问题无法对临时的右值对象进行修改和资源复用只能通过拷贝使用泛型编程中无法区分传入的参数是左值还是右值无法实现精准的参数转发而右值引用的出现完美解决了这两个问题。2. 右值引用的语法与本质右值引用是 C11 新增的引用类型用符号声明核心是专门绑定到右值临时对象、将亡值的引用。基础语法类型 引用名 右值表达式;右值引用的核心规则必须在定义时初始化且初始化后无法重新绑定到其他对象只能直接绑定到右值无法直接绑定到左值绑定到右值后会延长该临时右值的生命周期生命周期与右值引用变量一致可以通过右值引用修改绑定的右值对象右值引用变量本身是左值有名字、可通过取地址这是初学者最容易踩的坑#include iostream using namespace std; int getNum() { return 100; } void func(int rri) { rri 0; } int main() { // 1. 右值引用必须绑定右值 int ri0 42; // 正确绑定字面量纯右值 int ri1 1 2; // 正确绑定表达式结果纯右值 int ri2 getNum(); // 正确绑定函数返回值纯右值 // int ri3 ri0; // 报错ri0是右值引用变量本身是左值无法绑定 // 2. 可通过右值引用修改绑定的对象 ri0 100; cout ri0 ri0 endl; // 输出ri0 100 // 3. 可获取右值引用的地址证明它本身是左值 int* pi ri0; *pi 200; cout *pi *pi , ri0 ri0 endl; // 输出*pi 200, ri0 200 // 4. 右值引用作为函数参数接收右值 func(1 2); return 0; }3. std::move ()做了什么std::move()实现了资源的移动这是错误的。std::move()的本质不做任何资源移动、不生成任何机器码只是无条件地将一个左值强制转换为右值引用类型将亡值仅此而已。它的唯一作用就是让左值可以被右值引用绑定从而为后续的资源转移提供可能。真正的资源转移是在类的移动构造函数、移动赋值运算符中完成的std::move()只是打开了 “资源转移” 的入口。#include iostream #include string using namespace std; int main() { string str Hello World!; cout move前str str endl; // std::move将str左值转为右值触发string的移动构造函数 string tmp std::move(str); cout move后str str endl; // 结果未定义标准仅保证str可析构 cout move后tmp tmp endl; return 0; }注std::move()之后的原对象其资源已经被转移处于 “有效但未定义” 的状态只能对其进行析构或重新赋值绝对不能再访问其内部资源否则会出现未定义行为。4. 左值引用 vs 右值引用特性左值引用Type右值引用Type声明符号初始化要求必须初始化绑定后不可重新绑定必须初始化绑定后不可重新绑定直接绑定对象非 const 左值引用仅左值const 左值引用左值 右值仅右值纯右值 将亡值左值需通过 std::move 转换后绑定绑定对象的修改性非 const 左值引用可修改const 左值引用不可修改可修改绑定的右值对象const 右值引用除外本身属性左值有名字的右值引用变量是左值匿名右值引用是右值核心应用场景函数参数传递、避免拷贝、返回左值对象移动语义、完美转发、资源所有权转移引用折叠与任何引用折叠均为左值引用仅与右值引用折叠为右值引用其余均为左值引用能否为 nullptr不能必须绑定合法对象不能必须绑定合法对象四、右值引用的两大核心应用场景1. 移动语义告别无意义的深拷贝实现资源高效转移移动语义是右值引用最核心的价值它的核心思想是对于即将销毁的对象不做资源的深拷贝而是直接将其资源的所有权 “转移” 到新对象中避免了内存分配、数据复制和内存释放的巨大开销。移动语义的实现依赖于移动构造函数和移动赋值运算符二者的参数都是右值引用类型。1.1 无移动语义的痛点深拷贝的性能浪费先实现一个简单的字符串类看看没有移动语义时临时对象带来的性能开销#include iostream #include cstring using namespace std; class MyString { public: char* data; size_t len; // 普通构造函数 MyString(const char* str) { len strlen(str); data new char[len 1]; strcpy(data, str); cout 构造函数分配内存地址 (void*)data 内容 data endl; } // 拷贝构造函数深拷贝 MyString(const MyString other) { len other.len; data new char[len 1]; strcpy(data, other.data); cout 拷贝构造函数深拷贝内存新地址 (void*)data 内容 data endl; } // 拷贝赋值运算符深拷贝 MyString operator(const MyString other) { if (this other) { return *this; } // 释放自身原有资源 delete[] data; // 深拷贝源对象资源 len other.len; data new char[len 1]; strcpy(data, other.data); cout 拷贝赋值运算符深拷贝内存新地址 (void*)data 内容 data endl; return *this; } // 析构函数 ~MyString() { if (data) { cout 析构函数释放内存地址 (void*)data 内容 data endl; delete[] data; } else { cout 析构函数资源已转移无需释放 endl; } } }; MyString createString() { MyString str(Hello C); return str; // 返回临时对象触发拷贝构造 } int main() { MyString str1(Hello World); MyString str2 str1; // 触发拷贝构造 MyString str3 createString(); // 临时对象触发拷贝构造随后销毁 return 0; }此处每一次对象拷贝都会触发深拷贝重新分配内存、复制数据临时对象创建后很快被销毁造成了巨大的性能浪费。1.2 基于右值引用实现移动语义我们给 MyString 类添加移动构造函数和移动赋值运算符通过右值引用实现资源转移#include iostream #include cstring using namespace std; class MyString { public: char* data; size_t len; // 普通构造函数 MyString(const char* str) { len strlen(str); data new char[len 1]; strcpy(data, str); cout 构造函数分配内存地址 (void*)data 内容 data endl; } // 拷贝构造函数深拷贝 MyString(const MyString other) { len other.len; data new char[len 1]; strcpy(data, other.data); cout 拷贝构造函数深拷贝内存新地址 (void*)data 内容 data endl; } // 移动构造函数右值引用参数资源转移 // noexcept关键字告诉编译器该函数不会抛出异常STL容器会优先调用 MyString(MyString other) noexcept { // 直接转移源对象的资源无需深拷贝 data other.data; len other.len; // 源对象指针置空避免析构时释放资源 other.data nullptr; other.len 0; cout 移动构造函数转移资源目标地址 (void*)data endl; } // 拷贝赋值运算符深拷贝 MyString operator(const MyString other) { if (this other) { return *this; } delete[] data; len other.len; data new char[len 1]; strcpy(data, other.data); cout 拷贝赋值运算符深拷贝内存新地址 (void*)data 内容 data endl; return *this; } // 移动赋值运算符右值引用参数资源转移 MyString operator(MyString other) noexcept { if (this other) { return *this; } // 释放自身原有资源 delete[] data; // 转移源对象资源 data other.data; len other.len; // 源对象指针置空 other.data nullptr; other.len 0; cout 移动赋值运算符转移资源目标地址 (void*)data endl; return *this; } // 析构函数 ~MyString() { if (data) { cout 析构函数释放内存地址 (void*)data 内容 data endl; delete[] data; } else { cout 析构函数资源已转移无需释放 endl; } } }; MyString createString() { MyString str(Hello C); return str; } int main() { MyString str1(Hello World); MyString str2 std::move(str1); // 触发移动构造转移str1的资源 MyString str3 createString(); // 临时对象是右值触发移动构造 str3 MyString(Hello Move); // 临时对象触发移动赋值 return 0; }此处移动构造 / 移动赋值没有做任何深拷贝只是转移了指针的指向没有新的内存分配性能得到了提升。注移动构造 / 移动赋值的参数必须是非 const 右值引用因为我们需要修改源对象的指针将其置空强烈建议给移动构造 / 移动赋值添加noexcept关键字STL 容器如 vector在扩容时只有移动构造被声明为 noexcept才会优先调用移动构造否则会保守地调用拷贝构造函数当类没有自定义拷贝构造、拷贝赋值、析构函数时编译器会自动生成默认的移动构造和移动赋值函数如果自定义了上述函数编译器不会自动生成需要手动实现1.3 移动语义的常见场景STL 容器的优化C11 之后所有 STL 容器都实现了移动构造和移动赋值使用std::move()转移容器可以避免全量拷贝比如vectorint vec2 std::move(vec1);时间复杂度从 O (n) 降到 O (1)emplace 系列函数vector::emplace_back()、map::emplace()等函数通过完美转发直接在容器内存中构造对象避免了临时对象的拷贝和移动性能优于push_back()/insert()智能指针的资源转移std::unique_ptr无法拷贝只能通过移动语义转移所有权正是基于右值引用实现函数返回大对象返回大容器、大对象时编译器会优先进行 RVO/NRVO 返回值优化优化失效时会自动调用移动构造无需手动加std::move()2. 完美转发完美转发是右值引用的第二大核心应用它的核心目标是在模板函数中将参数原封不动地转发给另一个函数保留参数的左值 / 右值属性、const/volatile 修饰符。简单来说传入的是左值转发后还是左值传入的是右值转发后还是右值不会因为转发而改变参数的类型属性这就是 “完美” 的含义。2.1 完美转发的底层支撑完美转发的实现依赖三个 C11 的核心特性右值引用万能引用转发引用引用折叠规则std::forward()2.1.1 万能引用转发引用万能引用是指模板函数中形如T的参数它既可以绑定左值也可以绑定右值同时保留参数的所有类型属性。注意只有发生模板参数推导时T才是万能引用如果是具体类型的Type只是普通的右值引用只能绑定右值。// 模板参数推导T是万能引用 templatetypename T void func(T arg) { } // 具体类型int是普通右值引用 void func2(int arg) { } int main() { int a 10; func(a); // 正确万能引用绑定左值 func(10); // 正确万能引用绑定右值 // func2(a); // 报错普通右值引用无法绑定左值 func2(10); // 正确普通右值引用绑定右值 return 0; }2.1.2 引用折叠规则C 不允许引用的引用但在模板参数推导时会出现引用嵌套的情况此时编译器会执行引用折叠规则如下左值引用与 任何引用/折叠最终结果都是左值引用右值引用与 右值引用折叠最终结果才是右值引用嵌套类型折叠结果T TT TT TT T这个规则让万能引用可以同时适配左值和右值当传入左值int时T 被推导为intT int 折叠为int左值引用当传入右值int时T 被推导为intT int右值引用2.1.3 std::forward () 的作用std::forward()是实现完美转发的核心函数它的作用是有条件地进行类型转换当传入的是左值时不做任何转换依然返回左值当传入的是右值时转换为右值引用返回右值和std::move()的无条件转右值不同std::forward()是 “按需转换”完美保留参数的原始属性。2.2 完美转发的示例我们通过一个完整的例子看看完美转发的效果以及不使用完美转发的问题#include iostream #include utility using namespace std; // 重载函数区分左值和右值参数 void process(int x) { cout 左值引用版本被调用值 x endl; } void process(int x) { cout 右值引用版本被调用值 x endl; } // 不使用完美转发的模板函数 templatetypename T void noForward(T arg) { cout 无完美转发; process(arg); // arg是有名字的变量本身是左值永远调用左值版本 } // 使用完美转发的模板函数 templatetypename T void withForward(T arg) { cout 有完美转发; process(std::forwardT(arg)); // 完美转发保留原始左值/右值属性 } int main() { int a 5; cout 传入左值a endl; noForward(a); withForward(a); cout \n 传入右值10 endl; noForward(10); withForward(10); return 0; }运行结果 传入左值a 无完美转发左值引用版本被调用值5 有完美转发左值引用版本被调用值5 传入右值10 无完美转发左值引用版本被调用值10 有完美转发右值引用版本被调用值10可以看到不使用std::forward()时无论传入左值还是右值都会调用左值版本的 process 函数因为函数内部的 arg 是有名字的变量本身是左值。而使用完美转发后参数的左值 / 右值属性被完美保留正确调用了对应的重载函数。2.3 完美转发的常见场景STL 容器的 emplace 系列函数直接在容器内存中构造对象将用户传入的参数完美转发给对象的构造函数保留所有类型属性std::bind/std::function实现函数对象的封装和参数转发底层依赖完美转发线程库 std::thread将线程函数的参数完美转发到线程执行上下文泛型编程中的中间转发函数需要将参数透传给其他函数的模板场景五、高频踩坑点与实践建议1. 高频踩坑点坑 1std::move () 之后继续使用原对象std::move()之后原对象的资源已经被转移处于有效但未定义的状态此时访问其内部资源如 string 的字符、vector 的元素会触发未定义行为只能对其进行析构或重新赋值。坑 2对函数返回值使用 std::move ()很多人会写return std::move(obj);这是典型的错误写法。编译器默认会对返回的局部对象执行 RVO/NRVO 返回值优化直接在返回值地址构造对象零拷贝。而加了std::move()之后会阻止编译器的优化强制调用移动构造反而降低性能。坑 3误以为右值引用变量本身是右值有名字的右值引用变量本身是左值无法直接绑定到右值引用参数。如果需要在函数中转发右值引用形参必须使用std::move()或std::forward()。void func(int x) { } void test(int arg) { // func(arg); // 报错arg是右值引用变量本身是左值 func(std::move(arg)); // 正确 }坑 4给移动构造 / 移动赋值加 const 修饰移动构造 / 移动赋值需要修改源对象的指针将其置空加了 const 之后无法修改源对象只能做深拷贝完全失去了移动语义的意义。const 右值引用几乎没有使用场景不如直接用 const 左值引用。坑 5把普通右值引用当成万能引用只有在模板参数推导场景下的T才是万能引用类成员函数的模板参数如果没有推导过程也不是万能引用。class Test { public: // 这里的T不是万能引用因为类实例化时T已经确定没有参数推导 templatetypename T void func(T arg); };2. 实践建议只在需要转移资源的时候使用std::move()且确保 move 之后的对象不再使用实现移动构造 / 移动赋值时必须添加noexcept关键字确保 STL 容器能优先调用函数返回局部对象时不要加std::move()交给编译器做返回值优化泛型编程中需要转发参数时使用std::forward()实现完美转发不要用std::move()遵循 “三五法则”如果自定义了析构函数、拷贝构造函数、拷贝赋值运算符中的任意一个就应该同时实现或禁用移动构造、移动赋值运算符对于不需要拷贝、只需要转移所有权的对象如 unique_ptr、文件句柄禁用拷贝构造和拷贝赋值只实现移动构造和移动赋值感谢阅读本文如有错漏之处烦请斧正。

相关文章:

【C++】左值引用、右值引用

目录 一、右值引用的意义 二、基础:理解左值与右值 1. 左值(Lvalue,Locator Value) 常见的左值场景: 2. 右值(Rvalue,Read Value) 2.1 纯右值(prvalue)…...

Tower I3C Host Adapter 使用范例 (20)

Easyi3C是一家领先的嵌入式系统工具供应商,可简化各种通信协议的开发和调试。公司提供一系列产品,旨在帮助工程师和开发人员更高效地使用 I3C、I2C等协议。 基于Tower I3C Host Adapter 测试DDR5 RCD (4) 一 DDR5 RCD I3C背景介绍 在高性能计算和服务器…...

Qt进程间通信

QSharedMemory 共享内存(Shared Memory)是一种进程间通信(Inter-Process Communication, IPC)机制,允许多个进程共享同一块内存区域。共享内存提供了高效的数据交换方式,适用于需要频繁传递大量数据的场景。…...

Hive数仓分区设计与更新操作指南

目录 一、Hive 分区概述 1.1 分区的核心作用 1.2 分区的本质示例 二、分区设计原则 2.1 分区字段选择原则 2.2 分区粒度与数量控制 2.3 分区设计常见误区 三、分区表的创建 3.1 静态分区表 3.1.1 创建静态分区表 3.1.2 向静态分区表插入数据 3.2 动态分区表 3.2.1 …...

2026年最新免费5S管理系统盘点!盘点10个免费的5S系统!

在2026年制造业数字化转型的关键节点,寻找一套高效且低成本的5S管理系统已成为众多中小企业的迫切需求。面对市场上繁杂的软件选择,如何精准定位到真正的免费5S系统?本文为您带来2026年最新免费5S管理系统盘点,深度剖析当前市场格…...

一、STM32入门

用的是正点原子STM32F103MINI、JLINK v8 1.准备工作 1.1手册 1.1.1数据手册 STM32F103RCT6 开发板各个元件的特性。 1.1.2参考手册 在逻辑层面上,如何利用STM32F10X开发板各个部位的特性实现各种功能。 1.1.3厂家的学习开发手册 具体厂家设计的代码层面的如何学…...

《UNIX高级环境编程》第十三章 守护进程(一文读懂UNIX下守护进程)

一、守护进程的特征守护进程是一种生命周期较长的进程,常常在系统启动时被运行,在系统关闭时终止,并且没有关联的终端设备,是一个后台进程。一个系统中,父进程ID为0的一般是内核进程。进程1通常是init进程,…...

杰理AC695N/AC696N歌词回调

想要连接蓝牙播放音乐显示歌词杰理的SDK已经做好封装了, 等待我们去调用就可以了, ac695n和ac696n的sdk调用方法都一样下面开始还有一点最重要的是下面这个宏必须要打开, 最后连接蓝牙播放音乐就能在日志打印中看到歌词的回调了还有一个做法是可以把A2DP的这个宏关掉, 然后就可…...

配置中心的作用?Nacos 配置中心原理?

一句话回答:配置中心的作用,就是把分散在各个服务里的配置统一集中管理,并支持动态推送和环境隔离,避免每次改配置都去改代码、重启服务。 Nacos 官方也把自己定位成“动态配置服务”,强调配置的中心化、外部化和动态化…...

NPM Script 实战:常用命令设计与封装|Vue 工程化篇

【NPM Script】Vue 前端工程化实操:从核心封装逻辑到落地,彻底搞懂 npm run 常用命令最佳写法,避开端口占用、环境变量、多环境构建高频坑! 📑 文章目录 开篇一、NPM Script 是什么?为什么用它&#xff1f…...

KMP算法之 next 数组的计算

/*** brief 计算模式串的next数组(部分匹配表),并可视化计算过程* param pattern 模式串(待查找的基因片段)* param next 输出参数:存储next数组(长度需≥模式串长度)*/ void kmp_ge…...

发电机组并网技术研究

一、概述在现代电力供应体系中,柴发机组作为应急电源或后备电源,是应对市电中断、用电高峰负荷及特殊场景电力需求,保障电力持续、稳定供应的关键核心设备,其典型应用系统如下图1所示(图1:柴发机组典型供电…...

负载均衡策略有哪些?如何自定义?

你先记一句总纲:负载均衡策略,就是当一个服务有多个实例时,客户端或网关该按什么规则选一个实例去调用。常见负载均衡策略1. 轮询 Round Robin按顺序一个一个分配请求:第1个请求给实例A第2个请求给实例B第3个请求给实例C优点是简单…...

深度解构 BeyondMimic 引导扩散控制策略

深度解构 BeyondMimic 引导扩散控制策略 引导扩散就是先利用 Tracking 的方式训练出多个可以实现各种动作的小模型,随后利用这些小模型在仿真中生成大量的数据,用来训练出一个大模型,也就是蒸馏。但这里用的不是传统的蒸馏手段,我…...

全球爆火的龙虾杀入科研智能体赛道,字节跳动、微软以及英伟达等巨头也早已布局AI4Science领域

小罗碎碎念 如果说2020年至2023年是以AlphaFold为代表的模型在静态数据映射和结构预测上取得历史性突破的阶段,那么2025至2026年则标志着科学智能正式迈入“智能体(Agentic AI)”时代 。 在这一全新阶段,人工智能不再仅仅是被动…...

leetcode 1394. Find Lucky Integer in an Array 找出数组中的幸运数-耗时100

Problem: 1394. Find Lucky Integer in an Array 找出数组中的幸运数 耗时100%&#xff0c;固定数组统计频次&#xff0c;从高到低判断频次和数值是否相等 Code class Solution { public:int findLucky(vector<int>& arr) {vector<int> freq(501, 0);for(int&…...

leetcode 困难题 1392. Longest Happy Prefix 最长快乐前缀

Problem: 1392. Longest Happy Prefix 最长快乐前缀 滚动哈希的&#xff0c;取基26&#xff0c;模1e9 11&#xff0c;首先求出字符串的前缀哈希&#xff0c;前缀哈希用到了滚动哈希计算方式 后缀哈希&#xff0c;可以直接套公式求 像cbcb&#xff0c;前缀哈希这么算&#xf…...

AI新范式 02|拆解世界模型:它是如何理解物理规律的?

当AI学会了“重力加速度”&#xff0c;它就真正开始理解这个世界引言&#xff1a;从“知其然”到“知其所以然” 在第一篇中&#xff0c;我们谈到2026年是“世界模型元年”&#xff0c;NVIDIA Cosmos、Google DeepMind Genie等代表性工作正在重塑AI对物理世界的理解。但一个核心…...

告别绘图软件!Paperxie AI 科研绘图:10 次免费额度,让理工科论文可视化一步到位

paperxie科研绘图https://www.paperxie.cn/drawinghttps://www.paperxie.cn/drawing 在科研写作与论文发表的路上&#xff0c;「科研绘图」永远是那道绕不开的坎&#xff1a;Matplotlib 代码写了几百行还是跑不出理想图表&#xff0c;Origin 复杂的操作界面让新手望而却步&…...

环境变量与虚拟地址空间

环境变量与虚拟地址空间环境变量&#xff08;1&#xff09;问题引入&#xff08;2&#xff09;引入环境变量&#xff08;3&#xff09;环境变量和c代码关系1.用代码获取环境变量2.作用(4)添加环境变量&#xff08;5&#xff09;删除环境变量&#xff08;6&#xff09;set环境变…...

从零开始了解数据采集——制造业数字孪生

近年来&#xff0c;我国的工业领域正经历一场前所未有的数字化变革&#xff0c;从“双碳目标”到工业互联网平台的推广&#xff0c;国家政策和市场需求共同推动了制造业的升级。在这场变革中&#xff0c;数字孪生技术成为备受关注的关键工具&#xff0c;它不仅让企业“看见”设…...

2026 本科生论文工具盘点:9 款 AI 工具搞定初稿 / 绘图 / 排版 / AI 率

一、写在前面&#xff1a;论文季的「工具焦虑」&#xff0c;你需要一份精准选型指南 又到毕业季&#xff0c;朋友圈里满是「论文写到凌晨三点」「格式改到崩溃」「AI 率超标被导师打回」的吐槽。写毕业论文从来不是「敲字」那么简单&#xff1a;从选题定方向、初稿生成&#x…...

cpp刷题打卡20——前k个高频元素

前k个高频元素 题目描述&#xff1a; 给你一个整数数组 nums 和一个整数 k &#xff0c;请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。 题目代码&#xff1a; class Solution { public:class Mycompare{public:bool operator()(pair<int, int>&…...

基于docker的LLM服务部署

下载 拿qwen-3.5-9B 为例&#xff1a; https://www.modelscope.cn/models/Qwen/Qwen3.5-9B 首先下模型 git lfs install git clone https://www.modelscope.cn/Qwen/Qwen3.5-9B.git 然后下对应docker,框架我用的是vllm docker pull vllm/vllm-openai:qwen3_5 &#xff08;官…...

城市环境监测传感器—实时监测与分析环境数据

城市环境监测传感器是智慧城市建设中不可或缺的“感知神经”&#xff0c;通过实时监测与分析环境数据&#xff0c;为城市治理、生态保护与居民健康提供科学支撑。能够测量环境中的氧气、二氧化碳、氮气等气体成分&#xff0c;以及温度、湿度、噪音等参数。部分传感器还集成气象…...

【开题答辩全过程】以 户外用品比价系统为例,包含答辩的问题和答案

个人简介一名14年经验的资深毕设内行人&#xff0c;语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。感谢大家的…...

C的数组概念

一、一维数组1.1 概念数组是一组相同数据类型的元素的集合&#xff0c;这些元素在内存中是连续存储的&#xff0c;并且通过一个唯一的数组名称和索引来访问。1.2 定义一维数组的定义语法格式&#xff1a;数据类型 数组名 [元素个数];1.3 访问与操作1.3.1 访问访问数组元素通过下…...

电商系统商品管理模块避坑指南:Spring Boot+MySQL+Redis多数据源配置实战

电商系统商品管理模块避坑指南&#xff1a;Spring BootMySQLRedis多数据源配置实战 在电商系统开发中&#xff0c;商品管理模块作为核心业务组件&#xff0c;其稳定性和性能直接影响用户体验和平台收益。本文将深入剖析基于Spring Boot框架的多数据源配置实践&#xff0c;结合M…...

RK3588 Android 12 异显功能开发实战:命令行与Presentation双方案解析

1. 初识RK3588的异显能力&#xff1a;不止是“多接一个屏幕” 如果你手头有一块搭载了瑞芯微RK3588芯片的开发板&#xff0c;比如Firefly的ITX-3588J或者Rock 5B&#xff0c;并且已经刷好了Android 12系统&#xff0c;那你手里握着的其实是一个“多屏怪兽”的潜力股。很多朋友刚…...

新手必看:ARM、树莓派、Arduino和单片机到底该怎么选?从零到一的硬件开发指南

从零到一&#xff1a;如何为你的创意项目挑选最合适的硬件平台 最近几年&#xff0c;身边想动手做点“智能硬件”的朋友越来越多了。有人想给阳台的花花草草做个自动浇水器&#xff0c;有人想改造家里的灯光实现语音控制&#xff0c;还有人雄心勃勃地想从零开始造一台迷你机器人…...