我在SO上看到的几乎所有帖子都涉及到std::initializer_list
,人们往往会按价值传递std::initializer_list
。根据这篇文章:
http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/
如果想要复制传递的对象,则应该按值传递。但复制std::initializer_list
并不是一个好主意,因为
复制
std::initializer_list
不会复制基础对象。 在生命周期之后,不保证底层数组存在 原始初始化列表对象已结束。
那么为什么它的一个实例经常按价值而不是const&
传递,保证不会制作不必要的副本?
答案 0 :(得分:53)
价值通过,因为价格便宜。作为一个瘦包装器的std::initializer_list
很可能被实现为一对指针,因此复制(几乎)与通过引用一样便宜。另外,我们实际上并没有执行副本,我们(通常)执行移动,因为在大多数情况下,参数无论如何都是从临时构造的。但是,这对性能没有影响 - 移动两个指针与复制它们一样昂贵。
另一方面,访问副本的元素可能更快,因为我们避免了一个额外的解除引用(参考的那个)。
答案 1 :(得分:11)
可能由于相同的原因,迭代器几乎总是按值传递:复制迭代器被认为是“便宜的”。在initializer_list
的情况下,还有一个事实是大多数实例都是具有普通析构函数的临时实例,因此编译器可以直接在它放置函数参数的地方构造它们,而不需要复制。最后,事实上,像迭代器一样,被调用的函数可能想要修改该值,这意味着如果通过对const的引用传递它,它必须在本地复制它。
编辑:
只是概括:标准库通常假设最好按值传递迭代器,initializer_lists和函数对象。因此,您应该确保您设计的任何迭代器,iterator_lists或功能对象都很便宜,并且您应该在自己的代码中假设它们便宜复制。关于何时使用const的引用以及何时使用值的传统规则应该进行修改以反映这一点:
对于除迭代器,initializer_lists或函数对象之外的类类型,使用对const的引用传递;否则使用传递值。