禁止在C ++中进行类复制

时间:2012-11-19 15:09:30

标签: c++

当我想在C ++中禁止类复制时,我通常会声明私有运营商= 复制构造函数而我不会实施它们:

class MyClass
{
  char* _str;
  int _len;
  MyClass(const MyClass& rhs);            //No implementation
  MyClass& operator=(const MyClass& rhs); //No implementation
public:
  MyClass();
  MyClass(const char *);
}

这被认为是一种糟糕的风格吗?还有另一种方法吗?

3 个答案:

答案 0 :(得分:10)

在C ++ 11中,您可以显式删除这些函数(这比删除实现更受欢迎,因为它更易读,并且它总是会生成编译器错误,而不仅仅是链接器错误):

class MyClass
{
  char* _str;
  int _len;
  MyClass(const MyClass& rhs) = delete;
  MyClass& operator=(const MyClass& rhs) = delete;
public:
  MyClass();
  MyClass(const char *);
}

在C ++ 03中,您可以使用诸如boost::noncopyable之类的基类来实现相同的效果。这可能更具可读性(这与您的方法基本相同 - 这个基类具有私有拷贝构造函数和赋值运算符,因此继承它将使您的类不可复制):

class MyClass : boost::noncopyable
{
  char* _str;
  int _len;
public:
  MyClass();
  MyClass(const char *);
}

C ++中浅层和深层复制之间的区别完全在于如何实现复制构造函数(因为your assignment operator should be implemented using your copy-constructor)。如果你没有,那么既不能进行浅层复制也不能进行深度复制,如果有的话,则取决于它的实现方式。

答案 1 :(得分:3)

您可以创建预处理器宏来实现相同的目的,例如

#define DISABLE_COPY_AND_ASSIGN(className) private: \
    className(const className&); \
    className& operator=(const className&);

然后像这样使用它:

class MyClass
{
   DISABLE_COPY_AND_ASSIGN(MyClass)
public:
   ....
};

您也可以从boost::noncopyable派生:

class MyClass : boost::noncopyable
{
public:
   ....
};

此外,在C ++ 11中,您可以使用= delete

MyClass(const MyClass&) = delete;
MyClass& operator=(const MyClass&) = delete;

答案 2 :(得分:2)

有两种方法,都会导致编译错误:

C ++ 11方式:

class MyClass
{
  char* _str;
  int _len;
  MyClass(const MyClass& rhs) = delete;
  MyClass& operator=(const MyClass& rhs); = delete
public:
  MyClass();
  MyClass(const char *);
};

C ++ 03方式:

class MyClass
{
  char* _str;
  int _len;
public:
  MyClass();
  MyClass(const char *);

  MyClass(const MyClass& rhs);            //No implementation
  MyClass& operator=(const MyClass& rhs); //No implementation
}

如果您只是将复制构造函数声明为public,则会出现链接器错误,但编译将通过。由于编译在链接之前发生,因此打破编译会更好,因为你会更快地发现错误。