繁体   English   中英

C++ std::initializer_list 用法

[英]C++ std::initializer_list usage

我有几个关于initializer_list如何在 C++ 中工作的问题。 首先,假设我们有(为简单起见省略了std::):

initializer_list<uint32_t> lst({ 5, 4, 3 }); // (*)

在 Visual Studio 中,我稍微了解了 class 并发现只有这两个构造函数:

constexpr initializer_list() noexcept : _First(nullptr), _Last(nullptr) {}

constexpr initializer_list(const _Elem* _First_arg, const _Elem* _Last_arg) noexcept
    : _First(_First_arg), _Last(_Last_arg) {}

所以我的第一个问题是:上面标有 (*) 的行,是否有某种语法糖允许这种语法(或者可能是编译器的常规语法,以便他使用它并正确设置所有内容)?

从 class 的外观来看,一切都是 constexpr,所以我的结论是这一切都是在编译时完成的,但我找不到关于这个问题的任何具体解释。

下一个问题与上一个结论有点矛盾,但由于我不能 100% 确定发生的事情,我还是要问:如果我没有明确使用new initializer_list<int>({...}); initializer_list是否可以以任何方式使用动态 memory (是否有特定的用例)?

同样,这是一个愚蠢的问题,但我想确切了解 class 发生了什么,以及它如何与 memory 发生冲突。

第三个问题是,假设我们有一个如下所示的代码:

#include <iostream>
using namespace std;

class Test
{
    public: Test(initializer_list<uint32_t>&& lst)
    {
        cout << "Size: " << lst.size() << endl;

        for (const uint32_t* i = lst.begin(); i != lst.end(); ++i)
        {
            cout << " " << *i;
        }

        cout << endl << endl;
    }
};

int main(void)
{
    Test t1({ 4, 6, 3 });
    Test t2({ 6, 3, 2, 8 });

    return 0;
}

在这种情况下,除了与t1t2实例一起使用的方式之外,还有其他方法可以使用Test class 的构造函数吗? 当然,这甚至是正确的开始吗? cout确实打印出正确的值,但是我想确保没有任何格式不正确的内容,例如在cout之前被破坏的 'brace init list' {... }使用它们?

这让我很烦,因为我不了解 C++ 在编写此类内容时如何管理 memory。

1

所以我的第一个问题是:上面标有 (*) 的行,是否有某种语法糖允许这种语法(或者可能是编译器的常规语法,以便他使用它并正确设置所有内容)?

cppreference

笔记

尽管缺少构造函数,但可以创建非空初始化列表。 std::initializer_list 的实例在以下情况下被隐式构造:

  • 括号初始化列表用于列表初始化,包括函数调用列表初始化和赋值表达式(不要与构造函数初始化列表混淆)
  • 一个花括号初始化列表绑定到自动,包括在一个范围内的 for 循环中

2

下一个问题 [...]:如果我没有明确使用 new initializer_list({...});,initializer_list 是否可以以任何方式使用动态 memory(是否有特定的用例)?

你为什么要? 它们的主要目的是将参数列表传递给构造函数。 它们是由编译器动态构建的数组的轻量级包装器,允许您沿着以下行编写代码

std::string s1{'a', 'b', 'c', 'd'};

3a

在这种情况下,除了与 t1 和 t2 实例一起使用的方式之外,还有其他方法可以使用 Test class 的构造函数吗?

我真的不明白你在这里问什么。 我会这样写:

Test t1{ 4, 6, 3 };
Test t2{ 6, 3, 2, 8 };

3b

当然,这甚至是正确的开始吗?

您的代码没有任何问题。

3c

例如,在 cout 使用它们之前,'brace init list' {... } 被破坏(如果说这样的话甚至是可能的)?

再次来自cppreference

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

TL;DR:即使是临时代码也不会停止存在于两行随机代码之间。 您可以安全地使用 function 参数直到lst结束。

附言

只有在这个答案进行到一半时,我才意识到这不仅是 3 个问题,而且实际上是更多问题。 更好地专注于问题中的一个点。 如果您有更多问题,请打开更多问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM