【问题标题】:Why would std::initializer_list copy items?为什么 std::initializer_list 会复制项目?
【发布时间】:2019-01-24 10:48:59
【问题描述】:

我一直认为std::initializer_list 是一个轻量级代理对象,它只会从列表项中获取 const 引用,而不是复制它们。 但是后来我发现在这种情况下实际上执行了复制:

struct Test {
    Test() { 
        std::cout << this << " default ctor" << std::endl;
    }
    Test(const Test&) {
        std::cout << this << " copy ctor" << std::endl;
    }
    ~Test() {
        std::cout << this << " destructor" << std::endl;
    }
};

int main() {
    Test a;
    Test b;
    Test c;
    std::cout << "for begin" << std::endl;
    for(const auto& current : {a, b, c}) {
        std::cout << "Current: " << &current << std::endl;
    }
    std::cout << "for end" << std::endl;
}

以上代码的输出:

0x63e5acda default ctor
0x63e5acdb default ctor
0x63e5acdc default ctor
for begin
0x63e5acdd copy ctor
0x63e5acde copy ctor
0x63e5acdf copy ctor
Current: 0x63e5acdd
Current: 0x63e5acde
Current: 0x63e5acdf
0x63e5acdf destructor
0x63e5acde destructor
0x63e5acdd destructor
for end
0x63e5acdc destructor
0x63e5acdb destructor
0x63e5acda destructor

为什么在这种情况下 std::initializer_list 会复制项目,而不是仅仅获取它们的引用?有没有“优雅”的方式来写类似于for(auto&amp;&amp; x : {a, b, c}) 的东西,但又不复制现有项目?

【问题讨论】:

  • 我也很好奇如何做到这一点。 OP,您能否更新您的问题以寻求解决方案?
  • @texasbruce {&amp;a, &amp;b, &amp;c} 会避免复制
  • @M.M 那仍然是指针值的副本。显然 initializer_list 总是实例化一个新实例
  • @texasbruce 复制指针值没问题,它可能会生成与遍历引用“列表”相同的代码
  • @LanYi 你实际上可以使用std::ref 就像{ref(a), ref(b), ref(c)} 它返回一个reference_wrapper。但是为了获得最佳性能,指针可能是最好的。我认为这值得委员会提一下,看看它是否可以有一个更优雅的解决方案。

标签: c++


【解决方案1】:

来自std::initializer_list上的文档:

底层数组是一个 const T[N] 类型的临时数组,其中每个元素都是从原始初始化列表的对应元素复制初始化的(缩小转换无效除外) .底层数组的生命周期与任何其他临时对象相同,只是从数组初始化一个 initializer_list 对象可以延长数组的生命周期,就像将引用绑定到临时对象一样(有相同的例外,例如初始化非-静态类成员)。底层数组可以分配在只读内存中。

【讨论】:

  • 哎呀,没注意到std::initializer_list 有一个底层数组...看来我只能做{&amp;a, &amp;b, &amp;c} 以避免复制...
猜你喜欢
  • 2020-07-06
  • 2012-11-16
  • 1970-01-01
  • 1970-01-01
  • 2012-07-09
  • 2013-02-18
  • 1970-01-01
  • 1970-01-01
  • 2014-11-19
相关资源
最近更新 更多