[英]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;
}
在这种情况下,除了与t1
和t2
实例一起使用的方式之外,还有其他方法可以使用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.