【问题标题】:Why is not initializer_list in a class decleared a "const std::initializer_list & li"? [duplicate]为什么声明为“const std::initializer_list & li”的类中没有 initializer_list? [复制]
【发布时间】:2012-11-16 06:50:43
【问题描述】:

可能重复:
initializer_list and move semantics

环境: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

【问题讨论】:

  • initializer_list&lt;value_type&gt; 是一对指针。复制它非常便宜,并且不涉及您自己类型的任何副本。这里的问题具有不同的性质。 stackoverflow.com/questions/8193102/…
  • 请看我的测试文件和输出,你可能会发现它真的在做复制构造。
  • 请查看我链接的问题,您可能会发现其原因与通过值传递initializer_list 无关。

标签: c++ c++11


【解决方案1】:

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

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

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

【讨论】:

  • 谢谢!我acutually读过那篇文章,但不幸的是没看懂。我是 cpp 的新手,我正在努力阅读 STL 源代码。因为 c++-11 是新的,没有太多的东西,所以我可能只是犯了一些愚蠢的错误。
  • Stroustrup 和 dos Reis 的原始提案很好地解释了模型编译器如何实现 initializer_list 作为隐式数组的代理,为什么其中的元素是 const 以促进各种优化等:open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2100.pdf
猜你喜欢
  • 1970-01-01
  • 2020-07-06
  • 1970-01-01
  • 2016-07-28
  • 2015-02-14
  • 2012-07-09
  • 2013-02-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多