以下是 C ++ Primer 5th Edition (P.564):
作为一个例子,除了复制和移动分配 运算符,库 vector 类定义了第三个赋值 采用支撑元素列表的运算符(第9.2.5节,第337页)。我们 可以使用此运算符,如下所示:
vector<string> v; v = {"a", "an", "the"};
我们可以将此运算符添加到 StrVec 类(第13.5节,第526页)中:
class StrVec { public: StrVec &operator=(std::initializer_list<std::string>); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ };
在阅读时,我注意到这里使用的参数是一个值,而不是我预期的参考。所以我去了std::vector
的stl库代码。以下是我在文件stl_vector.h
中找到的内容:
/**
* @brief Builds a %vector from an initializer list.
* @param __l An initializer_list.
* @param __a An allocator.
*
* Create a %vector consisting of copies of the elements in the
* initializer_list @a __l.
*
* This will call the element type's copy constructor N times
* (where N is @a __l.size()) and do no memory reallocation.
*/
vector(initializer_list<value_type> __l,
const allocator_type& __a = allocator_type())
: _Base(__a)
{
_M_range_initialize(__l.begin(), __l.end(),
random_access_iterator_tag());
}
似乎用于std :: vector的参数也是一个值而不是引用,就像本书中所做的那样。但为什么? 使用引用不是更有效吗?
答案 0 :(得分:3)
基本上是一个指针(或者说是一对指针)正在传递。当您通过引用传递指针时,然后在引擎盖下,您将指针传递给指针。这只会增加低效率和复杂性。
对小型类型最有效的方法很大程度上取决于编译器和编译选项。
然而,作为一个简单的经验法则,小的内置类型参数按值传递,还包含由一个或两个这样的值组成的小结构,而较大的东西通过引用传递以提高效率(仅接受小问题)别名,因为它不是一个实践中的问题。)
答案 1 :(得分:3)
如果我们查看std::initializer_list的此引用,则说:
初始化列表可以实现为一对指针或指针和长度。复制std :: initializer_list不会复制基础对象。
它提供了一个强有力的提示,说明它为什么按值传递,因为复制一对指针或指针和长度并不是非常昂贵。引用实际上来自draft standard部分18.9
初始化列表段 2 。
如果我们查看其中一个earlier proposals,我们会发现相同的推理:
请注意,initializer_list是一个小对象(可能是两个单词),因此按值传递它是有意义的。通过值传递还简化了begin()和end()的内联以及size()的常量表达式求值。