【问题标题】:Using std::initializer_list[] as const list of lists of varying length使用 std::initializer_list[] 作为变长列表的 const 列表
【发布时间】:2019-09-11 17:55:14
【问题描述】:

我需要一个静态 const 可变长度列表列表(来自 Qt 的 QPointF),我直接在我的代码中初始化(见下文),以后只能以只读方式使用在。

我首先为此使用了const std::vector<QPointF>[],但后来我突然想到我可以改用const std::initializer_list<QPointF>[]const 甚至有必要吗?)。

static const std::initializer_list<QPointF> points[6] = {
        { { 0.50f, 0.50f } },
        { { 0.25f, 0.25f }, { 0.75f, 0.75f } },
        { { 0.25f, 0.25f }, { 0.50f, 0.50f }, { 0.75f, 0.75f } },
        { { 0.25f, 0.25f }, { 0.75f, 0.75f }, { 0.25f, 0.75f }, { 0.75f, 0.25f } },
        { { 0.25f, 0.25f }, { 0.75f, 0.75f }, { 0.50f, 0.50f }, { 0.25f, 0.75f }, { 0.75f, 0.25f } },
        { { 0.25f, 0.25f }, { 0.75f, 0.75f }, { 0.25f, 0.50f }, { 0.75f, 0.50f }, { 0.25f, 0.75f }, { 0.75f, 0.25f } },
    };

这是对std::initializer_list 的有效使用吗?对我来说,这看起来像是一个 hack,可能是因为 std::iniatilizer_list 的名称暗示了某种用途。对this 帖子的回答还提到初始化器列表旨在用于初始化例如容器。

我也考虑过const std::array&lt;...&gt;[],但是所有内部列表的长度必须相同。

如果std::initializer_list 在这里不是正确的选择,那么如何正确地做到这一点。由于堆分配,替代 std::vector 感觉不对。

【问题讨论】:

    标签: c++ c++11 nested-lists initializer-list compile-time-constant


    【解决方案1】:

    了解您的编译器输出可以帮助您做出此决定。 std::initializer_list&lt;&gt;just a thin wrapper around an array of objects

    如果您确实需要静态常量数据,std::initializer_list&lt;&gt;[] 是完全有效的(只要您不介意使用它的访问语法而不是像在 std::array&lt;&gt;std::vector&lt;&gt; 上找到的下标运算符)。 Clang 8 将数组中的每个 initializer_list 降低到其自己的固定长度数组 QPointF 结构。然后它使用对它创建的 QPointF 数组的引用填充另一个数组:

    // pseudo-C++ from Clang's generated output
    
    QPointF RT1[1] = { { 0.50f, 0.50f } };
    QPointF RT2[2] = { { 0.25f, 0.25f }, { 0.75f, 0.75f } };
    QPointF RT3[3] = { { 0.25f, 0.25f }, { 0.50f, 0.50f }, { 0.75f, 0.75f } };
    QPointF RT4[4] = { { 0.25f, 0.25f }, { 0.75f, 0.75f }, { 0.25f, 0.75f }, { 0.75f, 0.25f } };
    QPointF RT5[5] = { { 0.25f, 0.25f }, { 0.75f, 0.75f }, { 0.50f, 0.50f }, { 0.25f, 0.75f }, { 0.75f, 0.25f } };
    QPointF RT6[6] = { { 0.25f, 0.25f }, { 0.75f, 0.75f }, { 0.25f, 0.50f }, { 0.75f, 0.50f }, { 0.25f, 0.75f }, { 0.75f, 0.25f } };
    
    // Reference array:
    QPointF* points[6] = { RT1, RT2, RT3, RT4, RT5, RT6 };
    

    访问列表中的单个值

    (points[5].begin() + 3)->y
    

    降低到基本上相当于

    points[5][3].y
    // alternatively:
    (*(*(points + 5) + 3)).y
    // which is actually:
    (*(RT5 + 3)).y
    

    std::initializer_list&lt;&gt;::begin() 的实现可能不同。)

    因此,如果您不介意隐藏的取消引用或不同的语法样式,这很好。 (尽管您也会在数组或向量中使用 dereferenecs。)

    尝试不同的优化级别并查看结果:https://godbolt.org/z/Vwjbp2

    【讨论】:

      【解决方案2】:

      标准说

      initializer_list 类型的对象提供对 const E 类型对象数组的访问。

      这并不意味着这些对象将专门用作初始化其他对象的临时对象,尽管这无疑是主要的预期用途。该标准实际上提供了一个将其正确用作变量的示例。

      所以我看不出你所做的有什么问题。

      【讨论】:

        猜你喜欢
        • 2022-07-06
        • 1970-01-01
        • 2012-11-16
        • 1970-01-01
        • 2015-09-04
        • 2014-07-13
        • 1970-01-01
        • 2016-05-31
        • 1970-01-01
        相关资源
        最近更新 更多