★ 返回值选型速查
函数把结果交还调用方的方式与传参一一对应:按值、引用或指针。本页按返回方式归并选型。把结果装进返回值优先于增设输出参数,这是现行 Google Inputs and Outputs 的总口径。
先判断结果是否存在、是否可空、是否携带成败信息,再对照各节推荐方式。场景细节回链各使用场景章。
按值返回
默认方式。结果是新算出来的值时按值返回:int、double、enum class(GameStatus、CellState)、小结果类型(PlaceResult)都与按值传参同类,拷贝廉价,调用处无需管理生命周期。
片段:按值返回的正例
// 由对局玩家得到棋盘格子状态,按值返回。
CellState PlayerToCellState(Player player);
// 落子按值返回结果类型,成败信息随值交还调用方。
PlaceResult TryPlace(Move move);按值返回优先于输出参数:能用返回值表达的,就不要再设计一个 T& 出参。
引用返回
结果早已存在且函数只是提供访问入口时返回引用,例如容器元素的访问器。前提是对象生命周期明确:调用方使用返回值的期间,被引用的对象必须仍然存活。
片段:引用返回的正反例
// 正例:返回已存在的元素,生命周期由容器保证。
const std::string& Entry(std::size_t index) const;
// 反例:局部变量在函数结束时销毁,返回它的引用是悬空引用。
const std::string& Greeting() {
std::string local = "hello";
return local;
}指针返回
结果可能不存在时返回指针,用 nullptr 表达“没有找到”,调用方先判空再使用。堆上的所有权结果不用裸指针表达,用智能指针按值返回,所有权随返回值交还调用方。
片段:指针返回的正例
// 可空结果:找不到时返回 nullptr。
const Player* FindWinner(const Board& board);结果类型
业务操作的成败信息装进结果类型按值返回,例如 PlaceResult 表达“接受写入还是拒绝”,GameStatus 报告对局是否结束,这类信息属于正常业务路径,不用异常表达:
- 异常留给构造失败、越界
at等前置条件失败或无法继续的硬边界; what()用英文短句(如GetCellState: position is outside the board),不用日志框架拼消息;- 姊妹仓库的规则核心与可测试 API 也按这一口径选型。
容器上 [] 与 at 的检查差异见下标与 at。
常见错误
返回局部引用
局部变量随函数结束销毁,引用它的代码全部悬空,结果是新算出来的值就按值返回。
异常表达业务结果
落子被拒绝、查找失败是正常分支,用结果类型或 nullptr 表达,异常只留给真正的边界故障。
自测问题
先不要展开答案,试着自己把回答完整说出来,再展开对照。说不出来的部分,回到对应小节对照正文。
返回引用需要满足什么前提?
查看答案
被引用的对象在调用方使用返回值期间必须仍然存活。引用返回只用于访问已存在的对象,禁止返回局部变量。
业务操作的失败为什么用结果类型表达而不是异常?
查看答案
被拒绝的落子、未找到的查找是正常业务路径,调用方需要逐个处理。结果类型让成败随返回值交还,异常只留给无法继续的边界故障。
本章回顾
你现在能按返回方式选型:新算出的值按值返回,访问已有对象用引用返回,可空结果用指针返回,成败信息装进结果类型。传参一侧的选择见 ★ 传参选型速查。