我正在学习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性能问题?
答案 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)
在这种情况下,auto
和auto&
之间的另一个区别是auto&
将允许您修改向量中的值。这可能是不受欢迎的错误,正等待发生。理想情况下,如果您打算仅参考阅读,则应使用const参考:const auto &
当向量包含的对象多于基本数字或指针类型时,使用引用的好处是不会将整个对象复制到临时对象。如果对象具有任何深层复制语义,或者可能是shared_ptr,则可能会产生可避免的大量开销。
对于基本类型,副本通常非常快,因此首选单个副本,但是如果要求引用基本,然后多次使用该引用,则可以期望编译器优化程序做“正确的事”。对于模板编程,您应该更喜欢使用const-ref而不是副本,以在不知道类型时简化代码。