将不可复制的对象放入std容器中

|| 此类是否设计了标准的C ++ 0x方式来防止复制和分配,以保护客户端代码免受意外的ѭ0双重删除?
struct DataHolder {
  int *data;   // dangerous resource
  DataHolder(const char* fn); // load from file or so
  DataHolder(const char* fn, size_t len); // *from answers: added*
  ~DataHolder() { delete[] data; }

  // prevent copy, to prevent double-deletion
  DataHolder(const DataHolder&) = delete;
  DataHolder& operator=(const DataHolder&) = delete;

  // enable stealing
  DataHolder(DataHolder &&other) {
    data=other.data; other.data=nullptr;
  }
  DataHolder& operator=(DataHolder &&other) {
    if(&other!=this) { data = other.data; other.data=nullptr};
    return *this;
  }
};
您会注意到,我在这里定义了新的move和move-assign方法。我是否正确实施了它们? 我有什么办法-通过move和move-assign定义-将ѭ2放入标准容器中?像a3ѭ?我该怎么做? 我想知道,有些选择想到了:
// init-list. do they copy? or do they move?
// *from answers: compile-error, init-list is const, can nor move from there*
vector<DataHolder> abc { DataHolder(\"a\"), DataHolder(\"b\"), DataHolder(\"c\") };

// pushing temp-objects.
vector<DataHolder> xyz;
xyz.push_back( DataHolder(\"x\") );
// *from answers: emplace uses perfect argument forwarding*
xyz.emplace_back( \"z\", 1 );

// pushing a regular object, probably copies, right?
DataHolder y(\"y\");
xyz.push_back( y ); // *from anwers: this copies, thus compile error.*

// pushing a regular object, explicit stealing?
xyz.push_back( move(y) );

// or is this what emplace is for?
xyz.emplace_back( y ); // *from answers: works, but nonsense here*
在这里,ѭ5的想法只是一个猜测。 编辑:为了方便读者,我将答案纳入示例代码中。     
已邀请:
您的示例代码看起来基本上是正确的。 const
DataHolder &&other
(在两个地方)。 您的移动分配运算符中的
if(&other!=this)
看起来不必要但无害。 初始化程序列表向量构造函数将无法工作。这将尝试复制您的
DataHolder
,并且您会收到编译时错误。 带有rvalue参数的push_back和emplace_back调用将起作用。带有左值参数的(使用
y
)将给您编译时错误。 在push_back和emplace_back之间,使用它们的方式确实没有区别。 emplace_back用于当您不想在向量之外构造DataHolder时,而是传递参数以仅在向量内部构造一个。例如。:
// Imagine this new constructor:
DataHolder(const char* fn, size_t len);

xyz.emplace_back( \"data\", 4 );  // ok
xyz.push_back(\"data\", 4 );  // compile time error
更新: 我只是注意到您的移动分配运算符中有内存泄漏。
DataHolder& operator=(DataHolder &&other)
{
   if(&other!=this)
   {
      delete[] data;  // insert this
      data = other.data;
      other.data=nullptr;
   }
   return *this;
}
    
没有名称的临时对象,例如。
DataHolder(\"a\")
,在可用时移动。 C ++ 0x中的标准容器将在可能的情况下始终移动,这也允许将ѭ13放入标准容器中。 除此之外,您错误地执行了移动操作:
  // enable stealing
  DataHolder(const DataHolder &&other) {
    data=other.data; other.data=nullptr;
  }
  DataHolder& operator=(const DataHolder&&other) {
    if(&other!=this) { data = other.data; other.data=nullptr};
    return *this;
  }
您如何从一个恒定的物体移动?您不能只更改
other
data
,因为
other
是常数。将其更改为简单的
DataHolder&&
。     

要回复问题请先登录注册