【问题标题】:Is it safe to move elements of a initializer list? [duplicate]移动初始化列表的元素是否安全? [复制]
【发布时间】:2012-12-07 02:05:54
【问题描述】:

可能重复:
initializer_list and move semantics

在这段代码中:

#include <vector>
#include <initializer_list>

template<typename T>
class some_custom_container : public std::vector<T>
{
public:
   some_custom_container(const std::initializer_list<T>& contents)
   {
      for (auto& i : contents)
        this->emplace_back(std::move(i));
   }
};

class test_class
{};

int main()
{
    test_class a;

    some_custom_container<test_class> i = { a, test_class(), a };
}

如果我理解的话,{ a, test_class(), a } 中的所有对象都是安全构造的:命名对象被复制,未命名对象被移动以构造初始化器列表。之后,这个initializer_list 通过引用传递给some_custom_container 的构造函数。

然后,为了避免无用的双副本,我将它们全部移动以填充矢量。

这个构造函数安全吗?我的意思是,在一种奇怪的情况下,例如,如果 T 被评估为引用 & 或 &&,那么向量是否总是填充良好(包含安全对象)?

如果是这样的话,为什么stl容器的initializer_list构造函数实现不是这样实现的呢?据我所知,他们的构造函数复制而不移动内容。

【问题讨论】:

  • 它甚至无法编译,因为初始化列表仅提供对其内容的 const 访问,并且您无法从对 const 的引用中移动。另见:stackoverflow.com/questions/8468774/…
  • 这不会阻止它编译,只会移动。将调用复制构造函数。

标签: c++ c++11 containers move-semantics initializer-list


【解决方案1】:

initializer_list 仅提供 const 对其元素的访问。您可以使用const_cast 来编译该代码,但是这些移动最终可能会导致未定义的行为(如果initializer_list 的元素确实是const)。所以,不,这样做是不安全的。有are workarounds for this,如果你真的需要的话。

【讨论】:

  • 考虑在 cpptruths (cpptruths.blogspot.com/2013/09/…) 上描述的 in 成语。这个想法是在运行时确定左值/右值,然后调用移动或复制构造。即使 initializer_list 提供的标准接口是 const 引用,in 也会检测右值/左值。
  • @Sumant 这种巨大的混乱是否真的为性能或内存使用提供了任何可衡量的好处,如果是这样,足够多的这种好处足以抵消它看起来有多糟糕以及它需要大约一个小时来弄清楚它想做什么?我有点怀疑。
猜你喜欢
  • 2021-06-05
  • 2014-09-07
  • 2021-10-04
  • 2018-08-27
  • 1970-01-01
  • 1970-01-01
  • 2015-01-13
  • 1970-01-01
相关资源
最近更新 更多