【发布时间】: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: " << ¤t << 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&& x : {a, b, c}) 的东西,但又不复制现有项目?
【问题讨论】:
-
我也很好奇如何做到这一点。 OP,您能否更新您的问题以寻求解决方案?
-
@texasbruce
{&a, &b, &c}会避免复制 -
@M.M 那仍然是指针值的副本。显然 initializer_list 总是实例化一个新实例
-
@texasbruce 复制指针值没问题,它可能会生成与遍历引用“列表”相同的代码
-
@LanYi 你实际上可以使用
std::ref就像{ref(a), ref(b), ref(c)}它返回一个reference_wrapper。但是为了获得最佳性能,指针可能是最好的。我认为这值得委员会提一下,看看它是否可以有一个更优雅的解决方案。
标签: c++