为什么`std :: initializer_list`经常按值传递?

时间:2013-07-23 07:03:44

标签: c++ c++11

我在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&传递,保证不会制作不必要的副本?

2 个答案:

答案 0 :(得分:53)

价值通过,因为价格便宜。作为一个瘦包装器的std::initializer_list很可能被实现为一对指针,因此复制(几乎)与通过引用一样便宜。另外,我们实际上并没有执行副本,我们(通常)执行移动,因为在大多数情况下,参数无论如何都是从临时构造的。但是,这对性能没有影响 - 移动两个指针与复制它们一样昂贵。

另一方面,访问副本的元素可能更快,因为我们避免了一个额外的解除引用(参考的那个)。

答案 1 :(得分:11)

可能由于相同的原因,迭代器几乎总是按值传递:复制迭代器被认为是“便宜的”。在initializer_list的情况下,还有一个事实是大多数实例都是具有普通析构函数的临时实例,因此编译器可以直接在它放置函数参数的地方构造它们,而不需要复制。最后,事实上,像迭代器一样,被调用的函数可能想要修改该值,这意味着如果通过对const的引用传递它,它必须在本地复制它。

编辑:

只是概括:标准库通常假设最好按值传递迭代器,initializer_lists和函数对象。因此,您应该确保您设计的任何迭代器,iterator_lists或功能对象都很便宜,并且您应该在自己的代码中假设它们便宜复制。关于何时使用const的引用以及何时使用值的传统规则应该进行修改以反映这一点:

  

对于除迭代器,initializer_lists或函数对象之外的类类型,使用对const的引用传递;否则使用传递值。