跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
C++ 引用折叠
”︁
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
{{DISPLAYTITLE:C++引用折叠}} '''C++引用折叠'''(Reference Collapsing)是C++模板和类型推导中的一个重要规则,它决定了当引用嵌套时最终形成的引用类型。该概念在[[完美转发]](Perfect Forwarding)和通用引用(Universal Reference)的实现中起着关键作用。 == 基本概念 == 在C++中,引用本身不能形成引用的引用(即不存在`int&& &`这样的类型)。但在模板类型推导或`typedef`/`using`别名中,可能会间接产生引用的引用。引用折叠规则定义了这种情况下最终的类型。 引用折叠规则如下: * `T& &` → `T&` * `T& &&` → `T&` * `T&& &` → `T&` * `T&& &&` → `T&&` 用数学形式表示: <math> \begin{cases} A\& \& \equiv A\& \\ A\& \&\& \equiv A\& \\ A\&\& \& \equiv A\& \\ A\&\& \&\& \equiv A\&\& \end{cases} </math> == 代码示例 == 以下示例展示引用折叠在模板中的行为: <syntaxhighlight lang="cpp"> #include <iostream> #include <type_traits> template<typename T> void check_reference(T&& param) { if (std::is_lvalue_reference<T&&>::value) { std::cout << "T&& is lvalue reference\n"; } else if (std::is_rvalue_reference<T&&>::value) { std::cout << "T&& is rvalue reference\n"; } else { std::cout << "T&& is not a reference\n"; } } int main() { int x = 42; const int cx = x; // 示例1:传递左值 check_reference(x); // T = int& → T&& = int& && → int& // 输出: T&& is lvalue reference // 示例2:传递const左值 check_reference(cx); // T = const int& → T&& = const int& && → const int& // 输出: T&& is lvalue reference // 示例3:传递右值 check_reference(42); // T = int → T&& = int&& // 输出: T&& is rvalue reference } </syntaxhighlight> == 引用折叠与完美转发 == 引用折叠是实现完美转发的关键机制。`std::forward`利用引用折叠保留原始参数的值类别: <syntaxhighlight lang="cpp"> template<typename T> T&& forward(typename std::remove_reference<T>::type& arg) { return static_cast<T&&>(arg); } // 使用示例 template<typename T> void wrapper(T&& arg) { some_function(std::forward<T>(arg)); // 完美转发 } </syntaxhighlight> 当`T`是左值引用时,`forward`返回左值引用;当`T`是非引用或右值引用时,返回右值引用。 == 实际应用案例 == '''案例1:工厂函数''' <syntaxhighlight lang="cpp"> template<typename T, typename... Args> std::unique_ptr<T> make_unique(Args&&... args) { return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); } </syntaxhighlight> '''案例2:emplace_back实现''' 容器`emplace_back`方法使用引用折叠高效构造元素: <syntaxhighlight lang="cpp"> template<typename... Args> void emplace_back(Args&&... args) { // 使用完美转发将参数传递给构造函数 construct_at_end(std::forward<Args>(args)...); } </syntaxhighlight> == 类型推导中的引用折叠 == 引用折叠在`auto`类型推导中同样适用: <syntaxhighlight lang="cpp"> int x = 10; auto&& r1 = x; // auto = int& → int& && → int& auto&& r2 = 42; // auto = int → int&& </syntaxhighlight> == 常见误区 == 1. '''误认为所有`T&&`都是右值引用''':实际上在模板中`T&&`可能是通用引用,会根据传入参数决定最终类型。 2. '''忽略const的影响''':`const T& &&`会折叠为`const T&`,保留const限定符。 3. '''不理解引用折叠发生的场景''':只有在类型推导或别名中才会发生引用折叠。 == 总结 == 引用折叠是C++类型系统的重要组成部分,它: * 使通用引用和完美转发成为可能 * 保持代码的简洁性和效率 * 在模板元编程中广泛使用 理解引用折叠有助于深入掌握现代C++的移动语义和模板编程。 == 参见 == * [[右值引用]] * [[完美转发]] * [[类型推导]] [[Category:编程语言]] [[Category:C++]] [[Category:C++ 引用]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)