在范围for循环中的初始化列表

18

我有不同类型的对象,这些对象都是从一个共同的超类派生而来。我想知道在像下面这样的range for循环中使用std::initializer list是否存在任何缺点:

for(auto object: std::initializer_list<Object *>{object1, object2, object3}) {
}

这种做法是否完全正确和高效?或者使用数组会更好吗?对我来说,std::array 的解决方案似乎更加限制编译器,并且明确声明大小存在一个缺点:

for(auto object: std::array<Object*, 3>{object1, object2, object3}) {
}

有没有其他更好的方法来迭代一个明确给出的对象列表?

2个回答

19

在循环中没有必要使用冗长的std::initializer_list

#include <iostream>
#include <initializer_list>

struct B { virtual int fun() { return 0; } };
struct D1 : B { int fun() { return 1; } };
struct D2 : B { int fun() { return 2; } };

int main()
{
    D1 x;
    D2 y;

    B* px = &x;
    B* py = &y;

    for (auto& e : { px, py })
            std::cout << e->fun() << "\n";    
}

现场示例

如果你想在不定义pxpy的情况下进行即时操作,确实可以在循环内部使用std::initializer_list<B*>{ &x, &y }


1
似乎对我不起作用。正如我所写的,这些对象是具有共同超类型的不同类型:http://ideone.com/4KtpQw - Juraj Blaho
1
@JurajBlaho 试着写{&a, {&b}} - Johannes Schaub - litb
1
@JohannesSchaub-litb:只有至少一个元素是基础(目标)类型时才有效,但无论如何都是个不错的技巧。 - Juraj Blaho
一个稍微简短的解决方法:for (auto& e : { static_cast<B*>(&x), {&y} }) - Alexander Malakhov

12

你可以简单地写

for(auto object : {object1, object2, object3}) {
   // work
}

7
这个{ obj,obj }的东西叫什么?它只是一个初始化列表吗?还是有特殊的名称? - TankorSmash
2
当然,这只能在以下情况下直接使用:(A) objectN 已经是指针(否则效率低下,对象切片,仅更新真实元素的临时副本等),(B) 对象是上述公共类型;基类/派生类组合需要 AFAICT 的冗长语法。@TankorSmash 这是一个 _花括号初始化列表_,可以推导出各种类型,但 std::initializer_list 被赋予最高优先级。 - underscore_d

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接