如何使此C ++对象不可复制?

时间:2010-01-31 22:59:16

标签: c++ copy-constructor noncopyable

见标题。

我有:

class Foo {
   private:
     Foo();
   public:
     static Foo* create();
}

我需要做些什么让Foo无法复制?

谢谢!

10 个答案:

答案 0 :(得分:86)

class Foo {
   private:
     Foo();
     Foo( const Foo& ); // non construction-copyable
     Foo& operator=( const Foo& ); // non copyable
   public:
     static Foo* create();
}

如果你正在使用boost,你也可以从noncopyable继承:http://www.boost.org/doc/libs/1_41_0/boost/noncopyable.hpp

编辑:C ++ 11版本,如果您有支持此功能的编译器:

class Foo {
   private:
     Foo();
     Foo( const Foo& ) = delete; // non construction-copyable
     Foo& operator=( const Foo& ) = delete; // non copyable
   public:
     static Foo* create();
}

答案 1 :(得分:25)

使复制构造函数和赋值运算符也是私有的。只需声明即可,您无需提供实施。

答案 2 :(得分:17)

另一种禁止复制构造函数的方法,为方便起见,可以使用DISALLOW_COPY_AND_ASSIGN宏:

// A macro to disallow the copy constructor and operator= functions
// This should be used in the private: declarations for a class
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
  TypeName(const TypeName&) = delete;      \
  void operator=(const TypeName&) = delete

然后,在Foo课程中:

class Foo {
 public:
  Foo(int f);
  ~Foo();

 private:
  DISALLOW_COPY_AND_ASSIGN(Foo);
};

ref from google style sheet

答案 3 :(得分:16)

#include <boost/utility.hpp>
class Foo : boost::noncopyable {...

但正如Scott Meyers曾经说过的那样......“这是一个很好的课程,只是我发现这个名字有点不合适,不自然”,或类似的东西。

答案 4 :(得分:16)

在那里添加一点。

如前所述,传统解决方案是声明 Copy ConstructorAssignment Operator private 定义他们。

  • 因为它们是private,这将导致任何试图使用它们但无法访问该类私有部分的任何人的编译时错误 ...
  • 会在{em> link-time (如果你在那里检查那些)或大多数情况下以undefined symbol的形式发生错误的朋友(和类本身)可能在运行时(当试图加载库时)。

当然,在第二种情况下,这是非常麻烦的,因为您必须自己检查代码,因为您没有指示发生错误的文件和行。幸运的是,它只限于你的班级方法和朋友。


此外,值得注意的是,这些属性在继承和组合之路上是可传递的:编译器将仅生成Default ConstructorCopy ConstructorAssignment OperatorDestructor的默认版本。 // What does boost::noncopyable looks like > class Uncopyable { public: Uncopyable() {} private: Uncopyable(const Uncopyable&); Uncopyable& operator=(const Uncopyable&); }; 如果可能的话。

这意味着对于这四个中的任何一个,如果可以访问该类的所有基础和属性,则它们将自动生成

Uncopyable

这就是为什么从这个类继承(或者使用它作为属性)会有效地阻止你自己的类可以复制或赋值,除非你自己定义这些运算符。

一般来说,选择继承是因为组合有两个原因:

  • 该对象实际上是EBO,即使多态性可能没那么有用
  • 继承导致Empty Base Optimization或{{1}},而属性将是可寻址的,因此将占用内存(在类的每个实例中),即使它实际上不需要它,编译器也具有有可能不为基类添加这种开销。

或者,您可以将运算符声明为私有,而不是在您自己的类中定义它们,但代码不会自我记录,并且您将无法自动搜索这些类然后有这个属性(除非你有一个完整的解析器)。

希望这能为机制提供一些启示。

答案 5 :(得分:11)

在C ++ 11中,您可以通过在声明后放置= delete来显式禁用默认复制和赋值构造函数的创建。

来自Wikipedia

struct NonCopyable {
    NonCopyable() = default;
    NonCopyable(const NonCopyable&) = delete;
    NonCopyable & operator=(const NonCopyable&) = delete;
};

课程也是如此。

答案 6 :(得分:4)

使C ++对象不可复制的典型方法是显式声明复制构造函数和复制赋值运算符,但不实现它们。这将阻止编译器生成自己的。 (通常这与声明它们private一起完成,以便它生成编译错误而不是链接器错误。)

还有可以继承的boost::noncopyable类,这就是我上面描述的内容。

答案 7 :(得分:3)

将复制构造函数设为私有。

Foo(const Foo& src);

您不需要实现它,只需在头文件中声明它。

答案 8 :(得分:2)

这就是我使用的:

/* Utility classes */

struct NoCopy
{
public:
    NoCopy() {}
private:
    NoCopy(const NoCopy &);
};

struct NoAssign
{
private:
    NoAssign &operator=(const NoAssign &);
};

struct NonInstantiable
{
private:
    NonInstantiable();
};

struct NoCopyAssign : NoCopy, NoAssign
{
};
typedef NoCopyAssign NoAssignCopy;

在你的情况下:

struct Example : NoCopy
{
};

答案 9 :(得分:1)

C ++ 11中的一个好习惯是将副本构造函数和赋值声明为公开删除。 未私下删除,公开删除:https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-delete