2

可能重复:
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
4

1 回答 1

3

如果您仔细查看第一条评论中提供的链接,您将了解复制发生的原因:

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

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

于 2012-11-28T12:56:37.347 回答