news 2026/8/20 13:21:45

C++ 11 右值引用与默认参数详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++ 11 右值引用与默认参数详解

1. 默认参数(缺省参数)

在 C++ 中,函数可以拥有默认参数(也称为缺省参数)。当调用函数时,如果未提供某个参数,则使用该参数的默认值。

1.1 默认参数的声明与定义

默认参数在函数声明中指定,而不是在定义中。如果函数的声明和定义分开,默认值应写在声明中。

// .h 头文件 extern void func(int a = 0); // .cpp 源文件 #include "yang.h" void func(int a = 10) // 错误:默认值应只在声明中指定 { printf(""); }

正确做法:

// .h 头文件 extern void func(int a = 0); // .cpp 源文件 #include "yang.h" void func(int a) // 定义中不再写默认值 { printf("a = %d\n", a); }

1.2 默认参数的使用规则

默认参数必须从右向左连续提供,调用时从左向右传参,不能跳过中间的默认参数。

void func(int a = 5, int b = 4, int c = 3, int d = 2, int e = 1) { printf("a = %d b = %d c = %d d = %d e = %d \n", a, b, c, d, e); } int main() { func(); // a=5,b=4,c=3,d=2,e=1 func(50, 40); // a=50,b=40,c=3,d=2,e=1 // func(50, , 30); // 错误:不能跳过 b return 0; }

1.3 默认参数可以是表达式

默认参数可以是常量、全局变量,甚至是函数调用(但必须是编译时可确定的表达式)。

int my_rand() { srand(time(nullptr)); return rand() % 100; // 0~99 } void func(int a, int b = my_rand()) // 默认参数调用函数 { printf("a = %d b = %d \n", a, b); } int main() { func(1, 2); // a=1, b=2 func(12); // a=12, b=随机值 return 0; }

2. 左值与右值

C++11 引入了值类别的概念,每个表达式都有类型和值类别。

  • 左值 (lvalue):可以取地址的表达式,通常有持久的状态
  • 右值 (rvalue):不能取地址的表达式,通常是临时对象或字面量
int main() { int a = 10; // a 是 int 类型的左值 int* p = nullptr; // p 是 int* 类型的左值 char ch = 'a'; // ch 是 char 类型的左值 const int b = 20; // b 是 const int 类型的左值(常性左值) &a // 合法:a 是左值 // &10; // 错误:10 是右值 &p // 合法:p 是左值 // &nullptr // 错误:nullptr 是右值 &b // 合法:b 是左值(常性左值) return 0; }

3. 左值引用与右值引用

3.1 左值引用

传统的引用(&)是左值引用,只能绑定到左值。

int main() { int a = 10; int& ra = a; // 左值引用 const int& cra = a; // 左值常引用 const int b = 20; // int& rb = b; // 错误:不能将非 const 引用绑定到 const 对象 const int& crb = b; // 正确:const 引用可以绑定到 const 对象 return 0; }

3.2 右值引用

C++11 引入了右值引用(&&),只能绑定到右值。

int main() { int a = 10; int& ra = a; // 左值引用 const int& rb = a; // 左值常引用 int&& rr = 10; // 右值引用,绑定到字面量 10 // int&& rr2 = a; // 错误:不能将右值引用绑定到左值 cout << rr << endl; // 输出: 10 rr += 100; // 可以修改 cout << rr << endl; // 输出: 110 const int& crx = 30; // const 左值引用可以绑定到右值 // 编译器会生成临时对象:int tmp = 30; const int& crx = tmp; return 0; }

3.3 引用的特性

int main() { int a = 10; // 1. 引用必须初始化 int& ra = a; // 正确 // int& rb; // 错误:引用必须初始化 // 2. 不能引用引用(C++ 中没有引用的引用) int* p = &a int** pp = &p // 指针的指针 // int&& rra = ra; // 错误:不能有引用的引用 // 3. 引用不能为 NULL // int& rn = NULL; // 错误 return 0; }

4. 数组的引用

数组的引用语法比较特殊,需要括号:int (&rar)[n] = ar;

void funa(int *br, int n) // 数组退化为指针 { cout << "funa: br[5] size: " << sizeof(br) << endl; // 输出指针大小 } void funb(int (&rar)[5]) // 数组的引用,保留数组类型信息 { cout << "funb (&rar)[5] size: " << sizeof(rar) << endl; // 输出数组大小 } int main() { const int n = 5; int ar[n] = { 12, 23, 34, 45, 56 }; // 1. 变量的别名 int& a = ar[0]; // 数组元素的引用 // 2. 数组的别名(数组的引用) int(&rar)[5] = ar; // 必须指定正确的大小 cout << "main ar: size " << sizeof(ar) << endl; // 20 (5 * 4) funa(ar, n); // 输出指针大小(通常 4 或 8) funb(ar); // 输出数组大小 20 // 3. 指向数组的指针 int(*p)[n] = &ar; // 指向整个数组的指针 // 4. 指针数组的引用 int* br[n]; // 指针数组 int* (&rbr)[n] = br; // 指针数组的引用 return 0; }

5. 类类型的引用

引用不仅适用于内置类型,也适用于用户自定义的类类型。

class Int { // 类定义 }; int main() { Int obj; Int& robj = obj; // 类类型的左值引用 const Int& crobj = obj; // 类类型的 const 左值引用 const Int cobj; const Int& rcobj = cobj; // const 引用绑定 const 对象 // 对于类类型,const 引用绑定右值时不会生成临时对象(效率更高) const Int& rtemp = Int(); // 绑定到临时对象 return 0; }

6. 总结

  • 默认参数在函数声明中指定,从右向左连续提供
  • 左值可取地址,右值不可取地址
  • 左值引用&)绑定左值,右值引用&&)绑定右值
  • const 左值引用可以绑定左值和右值
  • 引用必须初始化,不能为 NULL,不能有引用的引用
  • 数组的引用需要特殊语法:int (&rar)[n] = ar;
  • 引用适用于所有类型,包括内置类型和用户自定义类型
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/20 13:19:06

ARM收购IoT服务商:从芯片IP到一站式开发平台的战略转型

1. 从芯片到服务&#xff1a;ARM收购IoT技术服务商的战略意图 最近看到一条新闻&#xff0c;ARM公司收购了一家IoT技术服务商。这消息乍一看&#xff0c;好像就是一个普通的商业并购&#xff0c;但如果你像我一样&#xff0c;在嵌入式开发和物联网这个圈子里泡了十几年&#xf…

作者头像 李华
网站建设 2026/8/20 13:18:19

Python进阶教程:Web开发入门(Flask)

目录Python进阶教程&#xff1a;Web开发入门&#xff08;Flask&#xff09;一、Flask 简介二、第一个 Flask 应用三、路由与参数四、模板渲染五、处理表单数据六、JSON API七、实战&#xff1a;待办清单 Web 应用总结Python进阶教程&#xff1a;Web开发入门&#xff08;Flask&a…

作者头像 李华
网站建设 2026/8/20 13:16:25

LLM原理与Prompt工程⑥-零基础面试保姆级教程

第 17 章&#xff1a;上下文工程 Context Engineering17.1 从 Prompt 工程到上下文工程2025 年起&#xff0c;行业共识发生了一次升级&#xff1a;单条提示词写得再好&#xff0c;决定 Agent 成败的是"每一步喂进上下文窗口的全部信息"的动态管理——系统提示、工具定…

作者头像 李华
网站建设 2026/8/20 13:14:50

ClickStack MCP 服务器基准测试:故障排查准确率提升 18%

本文字数&#xff1a;8714&#xff1b;估计阅读时间&#xff1a;22 分钟作者&#xff1a;Brandon Pereira编者按&#xff1a; 本文译自 ClickHouse 原博客。 原文围绕「探讨 AI 代理在可观测性领域的结构化评估方法」展开。该测试量化了 MCP 协议在故障排查中的效能优势&#x…

作者头像 李华
网站建设 2026/8/20 13:11:08

AI驱动的无线电信号生成:多智能体系统如何重塑波形设计与优化

1. 项目概述&#xff1a;当AI学会“调频”&#xff0c;RadioMaster如何重塑无线电信号生成 最近在AI和无线通信的交叉领域&#xff0c;一个名为“RadioMaster”的项目引起了我的注意。它不是一个简单的信号发生器软件&#xff0c;而是一个旨在实现“自主无线电信号生成”的多智…

作者头像 李华