为什么initializer_list不在一个类中清除一个"const std::initializer_list & li"?

Why is not initializer_list in a class decleared a "const std::initializer_list & li"?

本文关键字:一个 list initializer std li const 清除 为什么      更新时间:2023-10-16

可能的重复项:
initializer_list和移动语义

环境: Linux, g++-4.7

我使用了 std::vector 和我自己的一个类来测试这一点。我发现当使用 std::initializer_list 构造一个向量时,它实际上调用了自定义类的复制构造函数来制作一个临时对象。因此,我认为它的效率非常低,我用"const std::initializer_list&li"来代替它。

为什么它在STL库中真的很常见?例如:

// This is in STL: stl_vector.h
vector(initializer_list<value_type> __l, const allocator_type & __a = allocator_type())
//...

真的有什么东西漏过我的脑海吗?

我的测试代码如下所示:

#include <iostream>
#include <vector>
#include <initializer_list>
class Test
{
public:
    Test(const Test & t) : v(t.v) {
        std::cout << "Copy Cons" << std::endl;
    }
    Test(Test && t) : v(std::move(t.v)) {
        std::cout << "MC" << std::endl;
    }
    Test(int val) : v(val) {}
private:
    int v;
};
int main()
{
    std::vector<Test> vv({Test(0), Test(1), Test(2)});
    return 0;
}//main

它的输出:

Copy Cons
Copy Cons
Copy Cons

如果您仔细查看第一条评论中提供的链接,您将看到为什么会发生复制:

  1. 定义initializer_list时,编译器会将该列表的内容填充到内存块中的某个位置。然后,initializer_list仅包含指向该内存块的开头和结尾的两个指针。
  2. 将列表复制到构造函数中时,仅复制指针。
  3. 当向量分配了自己的内存时,它会将您的对象从列表的 chunk'o'mem 复制到它自己的内存中。这是您看到复制 ctor 的地方,而不是复制列表本身时。

您可以看到名为初始值设定项 lis 的语法元素,即大括号和逗号分隔值列表,作为编译器将该列表的内容放入只读内存块的指令。std::initializer_list只不过是该块的一对迭代器。