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

在我看到的几乎每个post中,涉及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&所保证,而不是一个不必要的副本呢?

它是有价值的,因为它很便宜。 std::initializer_list是一个很薄的包装器,很可能是作为一对指针来实现的,所以复制(几乎)像通过引用一样便宜。 另外,我们实际上并没有执行副本,而是(通常)执行副本,因为在大多数情况下,副本是从临时构build的。 但是,这对性能没有影响 – 移动两个指针与复制它们一样昂贵。

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

可能出于同样的原因,迭代器几乎总是按值传递:复制一个迭代器被认为是“便宜”的。 在initializer_list的情况下,也有一个事实,即大多数实例是临时的,具有简单的析构函数,所以编译器可以直接在函数参数的位置构造它们,而不需要拷贝。 最后,有一个事实,就像迭代器一样,被调用的函数可能需要修改这个值,这意味着如果它被一个对const的引用传递,它将不得不在本地拷贝它。

编辑:

只是为了概括:标准库在一般情况下进行了假设,最好是按值传递迭代器,初始化器列表和function对象。 因此,您应该确保您devise的任何迭代器,迭代器列表或function对象都很便宜,并且应该在自己的代码中假定它们便于复制。 关于何时使用对const的引用以及何时使用value的传统规则可能应该修改以反映这一点:

对于除迭代器,初始化器列表或函数对象以外的类types,请使用const引用来传递const; 否则使用价值传递。