我一直以为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})
的优雅写法,但不复制现有项目?
{&a, &b, &c}
会避免复制。 - M.Mstd::initializer_list
有一个底层数组,因此似乎{&a, &b, &c}
是唯一可行的解决方案...或者另外一种类似于some_custom_reference_holding_struct{a, b, c}
的方法也可能有效,但它们可能太长或太丑了,不好使用 :/ - LanYistd::ref
,像这样{ref(a), ref(b), ref(c)}
。它会返回一个reference_wrapper。但是为了获得最佳性能,指针可能是最好的选择。我认为这值得向委员会提出并看看是否有更优雅的解决方案。 - SwiftMango