当std :: initializer_list用作赋值参数时,为什么它不是引用类型?

时间:2014-01-14 02:12:28

标签: c++ c++11 vector stl

以下是 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的参数也是一个值而不是引用,就像本书中所做的那样。但为什么? 使用引用不是更有效吗?

2 个答案:

答案 0 :(得分:3)

基本上是一个指针(或者说是一对指针)正在传递。当您通过引用传递指针时,然后在引擎盖下,您将指针传递给指针。这只会增加低效率和复杂性。

对小型类型最有效的方法很大程度上取决于编译器和编译选项。

然而,作为一个简单的经验法则,小的内置类型参数按值传递,还包含由一个或两个这样的值组成的小结构,而较大的东西通过引用传递以提高效率(仅接受小问题)别名,因为它不是一个实践中的问题。)

答案 1 :(得分:3)

如果我们查看std::initializer_list的此引用,则说:

  

初始化列表可以实现为一对指针或指针和长度。复制std :: initializer_list不会复制基础对象。

它提供了一个强有力的提示,说明它为什么按值传递,因为复制一对指针或指针和长度并不是非常昂贵。引用实际上来自draft standard部分18.9 初始化列表 2

如果我们查看其中一个earlier proposals,我们会发现相同的推理:

  

请注意,initializer_list是一个小对象(可能是两个单词),因此按值传递它是有意义的。通过值传递还简化了begin()和end()的内联以及size()的常量表达式求值。