为什么使用引用作为迭代器

时间:2019-05-31 19:54:40

标签: c++ loops for-loop reference c++14

我正在学习std :: vector的emplace()并偶然发现以下代码:

// vector::emplace
#include <iostream>
#include <vector>

int main ()
{
  std::vector<int> myvector = {10,20,30};

  auto it = myvector.emplace ( myvector.begin()+1, 100 );
  myvector.emplace ( it, 200 );
  myvector.emplace ( myvector.end(), 300 );

  std::cout << "myvector contains:";
  for (auto& x: myvector)
    std::cout << ' ' << x;
  std::cout << '\n';

  return 0;
}

我想知道为什么在for循环中为什么他们使用引用auto&x而不是简单的副本,而我尝试了不使用&并且它的工作原理相同,这是否可以避免出现复制或aa性能问题?

2 个答案:

答案 0 :(得分:1)

就像您说的那样简单,它将是一个副本。因此,这确实是一种性能技巧,但是对于int来说,它不会更快,甚至会更慢。但是如果您有一个std::vector<std::string>包含百万个元素,那么它将有很大的不同。您可以自己尝试。

但是,如果要修改迭代容器的内容,则需要它。没有引用,您将更改副本,而不是容器内的元素。区别会在这里看到:

std::vector<int> numbers1 = {1,2,3,4};
std::vector<int> numbers2 = {1,2,3,4};
for(auto& x: numbers1) ++x;
for(auto x: numbers2) ++x;
assert(numbers1!=numbers2); // True

我也建议您使用auto&&而不是auto&,因为它对临时对象会更好,例如this answer

答案 1 :(得分:1)

在这种情况下,autoauto&之间的另一个区别是auto&将允许您修改向量中的值。这可能是不受欢迎的错误,正等待发生。理想情况下,如果您打算仅参考阅读,则应使用const参考:const auto &

当向量包含的对象多于基本数字或指针类型时,使用引用的好处是不会将整个对象复制到临时对象。如果对象具有任何深层复制语义,或者可能是shared_ptr,则可能会产生可避免的大量开销。

对于基本类型,副本通常非常快,因此首选单个副本,但是如果要求引用基本,然后多次使用该引用,则可以期望编译器优化程序做“正确的事”。对于模板编程,您应该更喜欢使用const-ref而不是副本,以在不知道类型时简化代码。