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

CppCon 2025 学习:C++23 deducing this

C++ 中的成员函数重载和 ref-qualifier(引用限定符),特别是在类似棋盘ChessBoard的场景下访问棋子时,如何根据对象是左值/右值const/非 const来返回不同类型的引用。

1⃣ 基本棋盘类访问函数

structChessBoard{ChessPiece board[64];// 假设 8x8 棋盘// 左值对象,非 constChessPiece&at(std::size_t row,std::size_t col)&{std::cout<<"lvalue non-const\n";returnboard[8*row+col];}// 左值对象,constChessPiececonst&at(std::size_t row,std::size_t col)const&{std::cout<<"lvalue const\n";returnboard[8*row+col];}// 右值对象,非 constChessPiece&&at(std::size_t row,std::size_t col)&&{std::cout<<"rvalue non-const\n";returnstd::move(board[8*row+col]);}// 右值对象,constChessPiececonst&&at(std::size_t row,std::size_t col)const&&{std::cout<<"rvalue const\n";returnstd::move(board[8*row+col]);}};

解释

  1. ref-qualifier&/&&
  • &表示只能在左值对象上调用
  • &&表示只能在右值对象上调用
ChessBoard cb;cb.at(0,0);// 左值 → 调用 & 版本ChessBoard{}.at(0,0);// 右值 → 调用 && 版本
  1. const 修饰符
  • const &→ 左值 const
  • const &&→ 右值 const
constChessBoard ccb;ccb.at(0,0);// const 左值 → 调用 const & 版本std::move(ccb).at(0,0);// const 右值 → 调用 const && 版本
  1. 返回值选择
  • 左值非 const → 返回ChessPiece&,可以修改棋子
  • 左值 const → 返回ChessPiece const&,只读
  • 右值非 const → 返回ChessPiece&&,可以移动棋子
  • 右值 const → 返回ChessPiece const&&,只读移动引用(很少用)

2⃣ 为什么要用这种写法?

  • 匹配对象的值类别(左值/右值)
  • 匹配对象的const 属性
  • 避免不必要的拷贝
  • 利用右值引用支持move semantics

3⃣ C++23 统一写法(this auto&&

C++23 支持成员模板写法

auto&&at(thisauto&&self,std::size_t row,std::size_t col){returnstd::forward<decltype(self)>(self).board[8*row+col];}

解释

  • this auto&& selfself会根据调用对象的值类别自动推导为:
    • ChessBoard&→ 左值
    • ChessBoard const&→ 左值 const
    • ChessBoard&&→ 右值
    • ChessBoard const&&→ 右值 const
  • std::forward<decltype(self)>(self)→ 完美转发,保证:
    • 左值返回左值引用
    • 右值返回右值引用
  • 返回类型auto&&→ 完美引用,自动匹配值类别和 const 性质

4⃣ 对应数学表示

假设棋盘数组:
b o a r d = [ b 0 , 0 , b 0 , 1 , . . . , b 7 , 7 ] board = [b_{0,0}, b_{0,1}, ..., b_{7,7}]board=[b0,0,b0,1,...,b7,7]
行列访问公式:
b o a r d [ r o w ∗ 8 + c o l ] board[row*8 + col]board[row8+col]
返回引用类型根据对象类别:
at ( r o w , c o l ) = { C h e s s P i e c e & 左值非 const c o n s t C h e s s P i e c e & 左值 const C h e s s P i e c e & & 右值非 const c o n s t C h e s s P i e c e & & 右值 const \text{at}(row,col) = \begin{cases} ChessPiece\& & \text{左值非 const} \\ const\ ChessPiece\& & \text{左值 const} \\ ChessPiece\&\& & \text{右值非 const} \\ const\ ChessPiece\&\& & \text{右值 const} \end{cases}at(row,col)=ChessPiece&constChessPiece&ChessPiece&&constChessPiece&&左值非const左值const右值非const右值const

5⃣ 使用示例

ChessBoard cb;constChessBoard ccb;cb.at(0,0);// lvalue non-constccb.at(0,0);// lvalue conststd::move(cb).at(0,0);// rvalue non-conststd::move(ccb).at(0,0);// rvalue const// C++23 版本cb.at(1,1);// 自动推导 & 完美转发std::move(cb).at(1,1);// 自动推导 && 完美转发

控制台输出:

lvalue non-const lvalue const rvalue non-const rvalue const

6⃣ 总结

  1. ref-qualifier(&/&&) 可以根据对象值类别重载成员函数
  2. const决定是否可以修改对象
  3. C++23 的this auto&&+auto&&返回类型 → 自动推导值类别 + const + 完美引用,代码简洁、可维护
  4. 访问棋盘公式统一:board[row*8 + col]

https://godbolt.org/z/Po9h58cjd

1⃣ 数据结构定义

structChessPiece{std::string name;};
  • 定义了一个ChessPiece结构体,表示棋子。
  • 里面只有一个成员name,用于存储棋子的名称(比如 “Pawn”, “Knight” 等)。
structChessBoard{ChessPiece board[64];// 8x8 棋盘
  • ChessBoard是棋盘类,用一个一维数组board[64]存储棋子。
  • 8x8 的棋盘可以通过索引计算访问:
    index = 8 × row + col \text{index} = 8 \times \text{row} + \text{col}index=8×row+col

2⃣ 四种成员函数重载(传统写法)

C++11/14/17 支持ref-qualified member functions,可以根据对象的左值/右值和 const 修饰选择不同的函数。

// 左值非 constChessPiece&at(std::size_t row,std::size_t col)&{std::cout<<"lvalue non-const\n";returnboard[8*row+col];}
  • &表示只能作用于左值对象
  • 返回可修改的引用,可以修改棋盘内容。
  • 调用例:cb.at(0,0)
// 左值 constChessPiececonst&at(std::size_t row,std::size_t col)const&{std::cout<<"lvalue const\n";returnboard[8*row+col];}
  • const&表示只能作用于 const 左值
  • 返回const 引用,不可修改棋子。
  • 调用例:ccb.at(0,0)
// 右值非 constChessPiece&&at(std::size_t row,std::size_t col)&&{std::cout<<"rvalue non-const\n";returnstd::move(board[8*row+col]);}
  • &&表示只能作用于右值对象
  • 返回右值引用,允许移动语义。
  • 调用例:std::move(cb).at(0,1)
// 右值 constChessPiececonst&&at(std::size_t row,std::size_t col)const&&{std::cout<<"rvalue const\n";returnstd::move(board[8*row+col]);}
  • const&&表示只能作用于右值且 const 对象
  • 返回const rvalue 引用,可以移动但不可修改内容。
  • 调用例:std::move(ccb).at(0,1)

✓ 总结:

  • 左值/右值 + const 修饰 => 形成 4 种组合。
  • 可以精确控制函数调用和返回类型,提高效率。
  • 特别适合带移动语义的类型(如std::stringstd::vector)。

3⃣ C++23this auto&&统一写法

auto&&at23(thisauto&&self,std::size_t row,std::size_t col){std::cout<<"C++23 this auto&& version\n";returnstd::forward<decltype(self)>(self).board[8*row+col];}
  • this auto&& selfC++23 新特性,把this当作普通参数
  • 优势:
    1. 无需写四个重载函数。
    2. 自动根据调用对象类型(左值/右值、const/非 const)完美转发。
  • std::forward<decltype(self)>(self)保证:
    • 左值调用 → 返回引用
    • 右值调用 → 返回右值引用
调用示例:
cb.at23(1,0);// 左值非 constccb.at23(1,0);// 左值 conststd::move(cb).at23(1,1);// 右值非 conststd::move(ccb).at23(1,1);// 右值 const

所有情况都只需要一个函数即可处理。

4⃣ 主函数分析

ChessBoard cb;constChessBoard ccb;cb.board[0].name="Pawn";cb.board[1].name="Knight";
  • 创建普通棋盘cb和 const 棋盘ccb
  • cb设置棋子名称。
  • 测试四种重载和 C++23 新特性。
cb.at(0,0);// 输出: lvalue non-constccb.at(0,0);// 输出: lvalue conststd::move(cb).at(0,1);// 输出: rvalue non-conststd::move(ccb).at(0,1);// 输出: rvalue const
  • 四种传统重载清晰展示调用规则。
  • C++23 版本:
cb.at23(1,0);ccb.at23(1,0);std::move(cb).at23(1,1);std::move(ccb).at23(1,1);
  • 统一函数 → 自动完美转发。
  • 输出都是:C++23 this auto&& version

5⃣ 代码理解总结


特性调用对象返回类型说明
ChessPiece& at() &左值非 const左值引用可修改棋子
const ChessPiece& at() const&左值 constconst 左值引用只读棋子
ChessPiece&& at() &&右值非 const右值引用可移动棋子
const ChessPiece&& at() const&&右值 constconst 右值引用可移动但只读棋子
auto&& at23(this auto&&)任意对象完美转发引用C++23 统一写法,自动适应左值/右值、const

  • 数学公式表示下标计算
    board[row][col] = board [ 8 ⋅ r o w + c o l ] \text{board[row][col]} = \text{board}[8 \cdot row + col]board[row][col]=board[8row+col]
  • 完美转发公式(C++23):
    return type = decltype(auto) of s t d : : f o r w a r d < d e c l t y p e ( s e l f ) > ( s e l f ) . b o a r d [ i n d e x ] \text{return type} = \text{decltype(auto)}\ \text{of}\ std::forward<decltype(self)>(self).board[index]return type=decltype(auto)ofstd::forward<decltype(self)>(self).board[index]
http://www.jsqmd.com/news/387624/

相关文章:

  • 2026 Agent元年!小白程序员必备:大模型学习路线图+精选资源,收藏这份高薪指南!
  • AI大模型从入门到精通:小白程序员必备学习路线(2026最新版)
  • 导师严选!继续教育专用AI论文软件 千笔·专业学术智能体 VS 学术猹
  • Comsol流固耦合注浆及冒浆分析。 采用其中达西定律模块及固体力学模块,通过建立质量源项、体...
  • 信息论与编码篇---欧式距离
  • 学长亲荐!更贴合研究生需求的降AI率平台,千笔·降AI率助手 VS 云笔AI
  • 导师严选! AI论文平台 千笔写作工具 VS WPS AI 更贴合自考需求
  • [NOIP2025 T2] 清仓甩卖 题解
  • 告别低效繁琐!降AI率平台 千笔·专业降AI率智能体 VS 文途AI
  • 实测对比后!千笔·专业学术智能体,专科生论文写作神器
  • 隧道内车距监测,低光环境测距防追尾,输出安全提醒。
  • 江苏美学植发医院排行更新,2026年这些医院上榜,植发/微针植发/发际线种植/美学植发/不剃发植发,美学植发机构推荐排行 - 品牌推荐师
  • 数据结构DS-KMP算法(c++实现)
  • 一键关闭Win杀毒和禁止系统更新,Windows轻松设置
  • SpringBoot智能图书馆座位预约管理系统开题报告
  • 2026年1月清障车实力厂家排行榜单,这些品牌不容错过!3万左右清障车/蓝牌重载清障车,清障车源头厂家哪个好 - 品牌推荐师
  • MG-Nav: 基于稀疏空间记忆的双尺度视觉导航 论文阅读 - 详解
  • 2026最新!8个一键生成论文工具测评:专科生毕业论文+开题报告写作全攻略
  • AtCoder Beginner Contest 445
  • 物理机理嵌入和自适应学习的机械早期故障诊断(Python)
  • 别再瞎找了!10个AI论文软件深度测评,自考毕业论文写作必备工具推荐
  • 交稿前一晚!10个降AIGC平台深度测评与推荐——MBA必看
  • 硬核解析 | 激光器冷却系统原理吃透+常见故障排查手册
  • 安全ftp服务配置
  • 拖延症福音 8个降AIGC平台测评:专科生降AI率必看攻略
  • 干货合集:8个AI论文工具测评!本科生毕业论文+科研写作必备神器
  • 2026年必学!收藏这份AI Agent学习指南,小白也能轻松入门大模型世界
  • 2026最新最全【大模型零基础入门到精通】大模型学习应用开发
  • 小白程序员必看:主流大模型推理部署框架深度解析与选型指南
  • 新手程序员轻松搞定大模型落地:解决幻觉与知识有限两大痛点,快速实现商业价值