initializer_list 和移动语义

新手上路,请多包涵

我可以将元素移出 std::initializer_list<T> 吗?

 #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));   // kosher?
    }
}

由于 std::intializer_list<T> 需要特别注意编译器并且没有像 C++ 标准库的普通容器那样的值语义,所以我宁愿安全也不愿问。

原文由 fredoverflow 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 482
1 个回答

不,这不会按预期工作;你仍然会得到副本。我对此感到非常惊讶,因为我认为 initializer_list 的存在是为了保留一系列临时对象,直到它们成为 move ‘d。

begin and end for initializer_list return const T * , so the result of move in your code is T const && 一个不可变的右值引用。这样的表达不能有意义地移开。它将绑定到 T const & 类型的函数参数,因为右值确实绑定到 const 左值引用,您仍然会看到复制语义。

可能是因为编译器可以选择将 initializer_list 静态初始化常量,但将其类型 initializer_listconst initializer_list 似乎更简洁 --- 由编译器自行决定,因此用户不知道是否期望 const 或来自 beginend 的可变结果。但这只是我的直觉,可能有一个很好的理由我错了。

更新: 我已经为 initializer_list 支持仅移动类型编写 了一个 ISO 提案。这只是初稿,还没有在任何地方实施,但您可以查看它以对问题进行更多分析。

原文由 Potatoswatter 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题