73

见标题。

我有:

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

我需要从这里做什么才能使 Foo 不可复制?

谢谢!

4

10 回答 10

99
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();
   public:
     Foo( const Foo& ) = delete; // non construction-copyable
     Foo& operator=( const Foo& ) = delete; // non copyable

     static Foo* create();
}

请注意,删除的方法应该是公开的:https ://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-delete

于 2010-01-31T23:02:22.867 回答
27

将复制构造函数和赋值运算符也设为私有。只需声明就足够了,您不必提供实现。

于 2010-01-31T23:00:58.393 回答
19
#include <boost/utility.hpp>
class Foo : boost::noncopyable {...

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

于 2010-01-31T23:04:51.660 回答
19

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

来自维基百科

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

当然,课程也是如此。

于 2012-11-29T15:16:45.117 回答
18

禁止复制构造函数的另一种方法是,为方便起见,可以使用 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);
};

来自谷歌样式表的参考

于 2010-02-01T08:31:21.920 回答
17

在那里添加一点。

如前所述,传统的解决方案是将and都声明,而不是定义它们。Copy ConstructorAssignment Operatorprivate

  • 因为它们是private,这将导致任何试图使用它们而无法访问类的私有部分的人出现编译时错误......
  • 这留下了朋友(和类本身),错误将以 的形式发生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,即使多态性可能没有那么有用
  • 继承导致EBOor Empty Base Optimization,而属性将是可寻址的,因此即使它实际上不需要它也会占用内存(在类的每个实例中),编译器有可能不为基类添加这种开销。

或者,您可以将运算符声明为私有而不在您自己的类中定义它们,但代码的自文档化程度较低,并且您将无法自动搜索具有此属性的那些类(除非您有成熟的解析器)。

希望这能对机制有所了解。

于 2010-02-01T08:17:03.387 回答
5

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

还有boost::noncopyable一个你可以继承的类,它完成了我上面描述的操作。

于 2010-01-31T23:02:05.487 回答
4

C++11 中的良好做法是将复制构造函数和赋值声明为公开删除。不私删,删:https ://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-delete

于 2018-08-21T15:35:27.483 回答
3

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

Foo(const Foo& src);

不需要实现,在头文件中声明即可。

于 2010-01-31T23:00:40.063 回答
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
{
};
于 2010-02-01T08:24:01.733 回答