如何将 C 数组转换为 std::initializer_list?

Posted

技术标签:

【中文标题】如何将 C 数组转换为 std::initializer_list?【英文标题】:How to convert C array to std::initializer_list? 【发布时间】:2019-10-22 02:02:28 【问题描述】:

我知道指向数组的指针及其大小。可以从中创建什么容器?我试着这样做:

std::initializer_list<int> foo(arr, arr + size);

它适用于 MSVC,但不适用于 gcc

【问题讨论】:

Initializer_list 构造函数非常简单:constexpr initializer_list() noexcept;。如果std::initializer_list&lt;int&gt; foo(arr, arr + size); 在 Visual Studio 下工作,那是因为他们添加了扩展。 initializer_list 设计用于大括号时间列表,它不是通用容器。您可以使用vectorspan 以及其他选项 这个列表的最终目标是什么?在需要之前传递数组和长度可能更容易。如果没有,我会从 std::vector 开始,可能会完全放弃数组。 引出一个问题:为什么不首先使用std::vector?无论如何,如果您以后只是要将它填充到容器中,那么该数组有什么用? 一个重要的补充——我不想复制内存。 MSVC 的 initializer_list 只是提供了一个用于遍历数组的接口。 【参考方案1】:

std::initializer_list 是专为支持列表初始化而设计的引用类型,只有 default-ctor 和隐式 copy-ctor。任何其他 ctor 都是扩展。

您可以做的是直接从迭代器范围初始化目标容器,而不涉及任何中间视图。

除非您更清楚,否则要使用的标准容器是std::vector。或者使用像std::span 这样的简单视图就足够了?

【讨论】:

std::span 正是我正在寻找的。谢谢!【参考方案2】:

如果您需要一个实际的数据拥有容器,那么您需要的是std::vector。这将花费您一份副本和一份分配的费用。如果您只需要像容器一样工作,那么您想要的是来自 C++20 的即将推出的std::span。它接受一个指针和一个大小,并将其包装在一个类似于数组的接口中。

MSVS 的使用

std::initializer_list<int> foo(arr, arr + size);

不是标准的。 Per the standard std::initiliazer_list 的唯一构造函数是

constexpr initializer_list() noexcept;

【讨论】:

跨度在这里太过分了。您可以从arr, arr + size 创建任何容器。 @NicolBolas 所有这些都会复制。跨度是“零成本”。 OP 问道,“可以从中创建什么容器?” span 不是容器。 initializer_list 只是达到目的的一种手段。 @NicolBolas Goiod 点。它列在[containers] 下,这让我很震惊。【参考方案3】:

这里有两个问题,每个问题都有自己的答案。


如何将 C 数组转换为 std::initializer_list?

你不能。这样做真的没有意义。 std::initializer_list 实际上只用于初始化(顾名思义)对象。它基本上是从 符号创建的,如下所示:

myObject obj = 0,1,2,3,4;

尝试创建 std::initializer_list 的实例在我能想到的任何其他意义上都没有真正的用处,尤其是因为 C++14 it's impossible to create at runtime 无论如何,因为它有一个 constexpr 构造函数。


如果你有一些对象foo 接受std::initializer_list,像这样:

class foo 
    foo(std::initializer_list list) 
        //...
    
;

而你想知道如何在没有std::initializer_list 的情况下创建这个对象,那么答案就是简单地添加另一个构造函数:

class foo 
    // an actual array
    foo(type arr[size]) 
        //...
    

    // as a pointer
    foo(type arr*, size_t size) 
        //...
    
;

如果您正在使用第三方库,或者您无法控制的其他库,并且没有其他构造函数,那么很可能它不打算以这种方式使用。在这种情况下,我会咨询您的文档或供应商。


可以从中创建什么容器?

任何sequence container。它们中的大多数都有某种构造函数,它接受指向对象的指针(实际上,它在技术上采用迭代器,但指针在这种情况下的工作方式相同)或数组。它们几乎是为从 C 数组轻松转换而设计的。您使用哪一种取决于您的情况。

此外,std::span(未列为“序列容器”)已被提及为可以从 C 数组以低成本创建的可能容器。不过,我不能亲自为他们担保,因为我对即将推出的标准不太熟悉。


最后说明:如果 MSVC 允许这样做,那么 a) 你可能在 C++11 中(尽管我无法确认 C++11 中是否允许这样做,只是构造函数不是 @987654336 @ 在 C++ 中)或 b)它是 MSVC 中的编译器错误。

【讨论】:

"你想知道如何在没有 std::initializer_list 的情况下创建这个对象,那么答案就是简单地添加另一个构造函数:" - 我可以在 tensorflow 内部类中做到这一点吗?他们只有std::initializer_list 作为输入,他们制作 - 没有其他。为什么 ??为什么从任何容器创建一个 std::initializer_list 构造器这么难?

以上是关于如何将 C 数组转换为 std::initializer_list?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 C 变长数组代码转换为 Rust?

如何将 C++ 或 C 中的字符串转换为整数数组?

如何将char数组转换为CString

如何在c ++中将int数组转换为字节数组[重复]

如何将 int 数组转换为单个 int c

如何使用 ctypes 将 Python 列表转换为 C 数组?