【问题标题】:Returning Iterators返回迭代器
【发布时间】:2019-07-31 20:01:11
【问题描述】:

使用 map.find() 或任何返回迭代器的函数。 将返回值存储为 ref 有什么好处?

const auto  it  = map.find(0);
const auto& it2 = map.find(0);

【问题讨论】:

  • 我怀疑你会看到任何性能差异。在您实际分析代码并确定性能不可接受之前,不应考虑此类微优化。
  • 启用优化器后,编译器可能会为这两种情况生成完全相同的代码。不要在没有使用分析器(在优化代码上)来证明它确实有所作为的情况下进行这样的微优化。
  • 存储对临时对象的引用通常是个坏主意。
  • @SidS 在这种情况下就好了

标签: c++ iterator auto


【解决方案1】:

如果您在for 循环范围内使用const auto& 可能会有所帮助,您也可以确定生命周期:

for(const auto& it : map)
{....}

正如@Ted 也指出这种形式的for 循环

for(const auto& [key, value] : the_map) 
 { ... }

否则,微优化(如果有的话)不值得它带来的潜在错误。 也许有一天另一个程序员删除了const 然后你有一个临时的引用。

【讨论】:

  • 甚至for(const auto& [key, value] : the_map) { ... }
  • “有一天另一个程序员删除了 const 然后你有一个临时的引用”除非你有讨厌的 MS 编译器,否则这将不起作用。
【解决方案2】:

有两个时刻使这种方法无用:

  1. 迭代器设计为轻量级对象,通过值传递和存储成本低廉。

  2. 即使在这种情况下你有重物,它也不会保存任何东西。这就是为什么。

想象一下这段代码:

HeavyObject foobar();

auto obj1 = foobar();
const auto &obj2 = foobar();

在早期的 C++ 中,由于第一种情况下可能调用了复制 ctor,因此第二种情况会更加优化。由于 RVO(返回值优化)自 C++17 以来是强制性的,因此不再是这种情况。因此,您的代码过去对比迭代器更复杂的对象有意义。在迭代器的情况下,即使没有启用优化,即使没有强制执行 RVO,您也不太可能看到任何性能差异。所以有些人可能认为这样的代码很好,但我会发现它不可读,因为迭代器通常按值传递,这样的代码至少会提出一个问题,为什么作者这样做?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-23
    • 2018-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-17
    • 2015-09-23
    • 2021-12-26
    相关资源
    最近更新 更多