首页 >后端开发 >C++ >我们可以安全地从 C 中的 `std::initializer_list` 中移动元素吗?

我们可以安全地从 C 中的 `std::initializer_list` 中移动元素吗?

Mary-Kate Olsen
Mary-Kate Olsen原创
2024-12-19 15:03:15356浏览

Can We Safely Move Elements from a `std::initializer_list` in C  ?

从 std::initializer_list 移动元素

在 C 中,一个初始化器列表,表示为 std::initializer_list,提出了一个关于其元素移动的问题元素。我们可以安全地从这样的列表中提取和移动元素吗?让我们研究一下这个问题。

在下面的代码片段中,函数 foo 接受一个初始化列表作为参数:

#include <initializer_list>
#include <utility>

template<typename T>
void foo(std::initializer_list<T> list)
{
    for (auto it = list.begin(); it != list.end(); ++it)
    {
        bar(std::move(*it)); // Intended to move the element
    }
}

出现这个问题是因为 std::initializer_list表现出区别于普通容器的独特特征。它的元素驻留在临时缓冲区中,并且不受与标准容器相同的值语义的约束。这引发了人们对成功移动的潜力的怀疑。

不幸的是,无缝元素移动的期望是没有根据的。尝试从初始值设定项列表中移动元素将产生意外结果。不是重新定位元素,而是创建副本。此行为源于 std::initializer_list 中的 begin 和 end 函数。返回 const T *,这会产生一个不可变的右值引用,表示为 T const &&。

因此,bar(std::move(*it)) 中使用的移动表达式绑定到 T 类型的函数参数const &,有效地保留了副本。

此限制的原因归因于编译器实例化的特权std::initializer_list 作为静态初始化常量。允许从开始到结束的可变结果会阻碍这种优化,从而在编译器的设计中引入复杂性。

尽管出现了意外的行为,但解决方案可能即将出现。 [ISO 提案](https://github.com/CaseyCarter/iso-changes/blob/master/icpp/p1716r4.md) 旨在引入对仅移动类型的初始值设定项列表支持。这项工作旨在增强语言的功能,并提供更一致的方法来处理初始化列表和移动语义。

以上是我们可以安全地从 C 中的 `std::initializer_list` 中移动元素吗?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn