在C++中插入容器时如何处理不可复制的对象

dbb*_*bbd 12 c++ noncopyable

我正在寻找处理不可复制对象的最佳实践.

我有一个互斥类,显然不应该是可复制的.我添加了一个私有拷贝构造函数来强制执行.

这破坏了代码 - 有些地方只需要修复,但我有一个通用的问题,一个类,使用互斥量作为数据成员,或通过继承,被插入到容器中.

这通常发生在容器初始化期间,因此互斥锁尚未初始化,因此可以,但没有复制构造函数它不起作用.更改容器以包含指针是不可接受的.

有什么建议吗?

pet*_*hen 11

三个解决方案:

1.使用指针 - 快速解决方法是使其成为指针的容器 - 例如a shared_ptr.

如果你的对象真的是不可复制的,那将是"好"的解决方案,并且不可能使用其他容器.

2.其他容器 - 或者,您可以使用非复制容器(使用就地构造),但它们不常见且与STL大部分不兼容.(我已经尝试了一段时间,但这根本不好)

如果您的对象是真正的不可复制的,那将是"上帝"解决方案,并且使用指针是不可能的.

[编辑]使用C++ 13,std :: vector允许inplace构造(emplace_back),并且可以用于实现移动语义的不可复制对象.[/编辑]

3.修复你的可复制性 - 如果你的类是可复制的,并且互斥锁不可复制,你"只需"修复复制构造函数和赋值运算符.

编写它们很痛苦,因为您通常必须复制并分配除互斥锁之外的所有成员,但通常可以通过以下方式简化:

template <typename TNonCopyable>
struct NeverCopy : public T 
{
    NeverCopy() {}
    NeverCopy(T const & rhs) {}

    NeverCopy<T> & operator=(T const & rhs) { return *this; }
}
Run Code Online (Sandbox Code Playgroud)

并将你的互斥成员改为

NeverCopy<Mutex> m_mutex;
Run Code Online (Sandbox Code Playgroud)

不幸的是,使用该模板会丢失Mutex的特殊构造函数.

[编辑]警告: "修复"复制CTor/asignment通常要求您在复制构造上锁定右侧,并在分配时锁定双方.不幸的是,没有办法覆盖copy ctor/assignment 调用默认实现,所以NeverCopy没有外部锁定,这个技巧可能对你不起作用.(还有一些其他解决方法有其自身的局限性.)


Pau*_*ams 3

如果一个对象是不可复制的,那么通常有一个很好的理由。如果有充分的理由,那么您不应该通过将其放入尝试复制它的容器来破坏它。

  • 这是一个很好的一般性建议,所以我不会对你投反对票。但这也是一个没有答案的问题,所以我很想这么做。 (6认同)
  • 事实上,这是一个答案。DBBD 的要求是错误的。Visage 告诉他出了什么问题:声称对象是不可复制的,但却在复制它们的容器中使用它们。这是无意义的。此外,DBBD 甚至没有说明为什么使用指针是不可接受的,而它应该是这样的(最有可能)。 (6认同)
  • +1 无所不能。这是一个没有答案的问题。它甚至不能帮助OP弄清楚*他的问题是什么*,它只是告诉他“你很愚蠢”。---- 即使互斥锁是不可复制的,为什么聚合互斥锁的对象应该是不可复制的呢?(*答案:因为它是默认的*)。根据我的经验,这里的解决方案通常是修复复制+赋值,而不是“不复制”。 (6认同)