Google C++每周贴士 #24: 复制简明判定法

(原文链接:https://abseil.io/tips/24 译者:clangpp@gmail.com)

每周贴士 #24: 复制简明判定法

“模仿别人是必要的,但重复自己是可悲的。”——巴勃罗·毕加索

注:参阅TotW #55TotW #77以获取关于命名计数和复制与移动对比的指导。

一个名字,没有复制;两个名字,两个副本

(译者注:我通常记为“有多少名字,就有多少副本”)

在任何作用域内(包括触发RVO(返回值优化,译者注)的情况),要知道发生了多少次复制,只需要检查你的数据有多少个名字。

在任意时刻,如果两份数据有两个有效的名字,那这些数据就有两个副本。 作为一个很好的近似,在除此以外的情况下,编译器会(而且常常是必须)避免复制。

在STL容器的移动语义和编译器的“省略复制构造”之间,我们正在快速地收敛到前面的定则,它不但提供了副本数量的下限,而且提供了保证。如果你的基准测试显示了比预期更多的复制,那很可能是一个编译器bug;你的编译器可能需要一个修复补丁。

因此,如果你的代码中,一份数据在某个时间点有两个名字,那么你应该期待有一次复制。如果你避免了指向一份数据的多余的名字,那么你在帮助编译器移除不必要的复制。

示例

通过几个例子,我们来看看实践中是怎么使用这个定则的:

std::string build();

std::string foo(std::string arg) {
  return arg;  // 没有复制,数据`arg`只有一个名字。
}

void bar() {
  std::string local = build();  // 只有一个实例,只有一个名字

  // 没有复制,引用不会触发复制
  std::string& local_ref = local;

  // 一次复制操作,现在同样的数据(`local`中的内容,译者注)有了两个名字。
  std::string second = foo(local);
}

大部分情况下,这些都不重要。相比于担心复制和效率,代码的可读性和一致性要重要得多。一如既往:优化之前先分析。(译者注:这是Google内部的一个常识,因此称为一如既往。我个人称之为“不要瞎优化”。)当然,如果你正在从头开始写新代码——而且能够提供干净和一致的API来返回值——不要为“可能”的复制而伤害你的API:对于复制,你所学到的十年前的所有知识都是错的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值