以下摘自C++入门第5版(第564页):
例如,除了复制和移动分配之外运算符,库向量类定义第三个赋值采用大括号元素列表的运算符(§ 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>); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ };
在阅读时,我注意到此处使用的参数是一个值,而不是我预期的引用。所以我去了 stl 图书馆代码进行std::vector
.以下是我从文件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 的参数也是一个值,而不是像本书中那样的引用。但是为什么?使用引用不是更有效吗?
如果我们看一下这个 std::initializer_list 的参考,它说:
初始值设定项列表可以实现为一对指针或指针和长度。复制 std::initializer_list 不会复制基础对象。
这给了你一个关于为什么它是按值传递的强烈提示,因为复制一对指针或一个指针和一个长度并不是很昂贵。该引用实际上来自标准草案部分18.9
初始值设定项列出了第 2 段。
如果我们看一下前面的提案之一,我们会发现相同的推理:
请注意,initializer_list是一个小对象(可能是两个词),因此按值传递它是有意义的。按值传递还简化了 begin() 和 end() 的内联以及 size() 的常量表达式计算。
一个指针(或者更确切地说是一对指针)。当您通过引用传递指针时,在后台您将指针传递给指针。这只会增加效率低下和复杂性。
对于小型类型最有效的方法在很大程度上取决于编译器和编译选项。
尽管如此,作为一个简单的经验法则,小型内置类型参数是按值传递的,也包含由一个或两个此类值组成的小结构,而较大的内容则通过引用传递以提高效率(只是接受别名的小问题,因为它不是一个实践问题)。