C++ 我如何制作这个C++;对象不可复制?

C++ 我如何制作这个C++;对象不可复制?,c++,copy-constructor,noncopyable,C++,Copy Constructor,Noncopyable,见标题 我有: class Foo { private: Foo(); public: static Foo* create(); } 我需要从这里做些什么才能使Foo不可复制 谢谢 将副本构造函数设为私有 Foo(const Foo& src); 您不需要实现它,只需在头文件中声明它。将复制构造函数和赋值运算符也设置为私有。只是声明足够了,不必提供实现。 < P>典型的使C++对象不可复制的方法是显式声明复制构造函数和复制赋值运算符,但不实现它们。这

见标题

我有:

class Foo {
   private:
     Foo();
   public:
     static Foo* create();
}
我需要从这里做些什么才能使Foo不可复制


谢谢

将副本构造函数设为私有

Foo(const Foo& src);

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

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

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

还有一个类可以从中继承,它实现了我上面描述的功能

class Foo {
   private:
     Foo();
     Foo( const Foo& ); // non construction-copyable
     Foo& operator=( const Foo& ); // non copyable
   public:
     static Foo* create();
}
如果您使用的是boost,还可以从noncopyable继承:

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

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

     static Foo* create();
}
请注意,删除的方法应该是公共的:

#include
类Foo:boost::不可复制{。。。
但正如斯科特·迈尔斯(Scott Meyers)曾经说过的那样……“这是一个很好的课程,只是我觉得这个名字有点不自然,或者类似的东西。”

如前所述,传统的解决方案是将
复制构造函数和
赋值操作符声明为
私有
,而不声明为定义它们

  • 由于它们是私有的,这将导致任何试图使用它们但无法访问类的私有部分的人出现编译时错误
  • 剩下的朋友(以及类本身)的错误将以
    未定义符号的形式出现,无论是在链接时(如果您在那里检查),还是在运行时(尝试加载库时)
当然,在第二种情况下,这相当麻烦,因为您必须自己检查代码,因为您不知道发生错误的文件和行。幸运的是,它仅限于您的类方法和朋友


另外,值得注意的是,这些属性在继承和组合过程中是可传递的:编译器只会生成
默认构造函数
复制构造函数
赋值运算符
析构函数
的默认版本(如果可能)

这意味着,对于这四个类中的任何一个,只有当类的所有基和属性都可以访问它们时,才会自动生成它们

// What does boost::noncopyable looks like >
class Uncopyable {
public:
  Uncopyable() {}

private:
  Uncopyable(const Uncopyable&);
  Uncopyable& operator=(const Uncopyable&);
};
这就是为什么从该类继承(或将其用作属性)将有效地防止您自己的类可复制或可分配,除非您自己定义这些运算符

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

  • 该对象实际上是不可压缩的,即使多态性可能没有那么有用
  • 继承导致
    EBO
    空基优化
    ,而属性将是可寻址的,因此将占用内存(在类的每个实例中),即使它实际上并不需要它,编译器也有可能不为基类添加此开销
或者,您可以将操作符声明为private,而不在自己的类中定义它们,但是代码的自文档化程度会降低,并且您将无法自动搜索具有此属性的类(除非您有一个完整的解析器)

希望这能对这个机制有所帮助。

这就是我使用的:

/* 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
{
};

另一种禁止复制构造函数的方法是,为了方便起见,可以使用“禁止复制”和“分配”宏:

// 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);
};

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

发件人:


当然,类也是如此。

C++11中的良好实践是将复制构造函数和赋值声明为已公开删除。
未私下删除,公开删除:< /P>引用引用上下文的任何链接:有效C++(第三版)-Scott Meyers,第6项注意,从这样的实用程序类继承可能会对类大小产生不利影响,具体取决于体系结构ABI。请参阅以获取详细信息。诚然,变更集只提到了安腾,而没有提到其他内容——但值得依赖其他体系结构吗?可能。这是一个明确的风险,并且声明了私有的NSurror和赋值运算符同样适用。您的解决方案与一些编译器不一样。一些C++编译器要求如果声明类成员函数,则必须定义它,即使它从不用于代码。因此,您需要使用{}。使用上面的两个函数声明。@三位,如果您说“两个函数”是指具有一个参数的构造函数和析构函数,这些是Declaration,程序员已经知道这些将在其他地方有定义。除此之外,这与公认的答案相同。@ThreeBit:你的意思是哪个编译器?如果它们这样做,它们就不符合标准。@Sebastian,那不是真的。如果声明了类构造函数,则必须在某个地方定义它。事实是在一些流行的编译器中,如果函数未显式调用,则忽略了类成员函数的定义,这是对语言的编译器扩展。Green Stand C++编译器是一个严格的例子。在C++标准中,没有任何位置需要编译器跳过成员F的链接。如果不使用,请使用unction。请随意查找此类子句。也许您可以找到一个。@3bit:有趣的讨论。我在标准中发现:“最多应有一个定义”
class Foo {
 public:
  Foo(int f);
  ~Foo();

 private:
  DISALLOW_COPY_AND_ASSIGN(Foo);
};
struct NonCopyable {
    NonCopyable() = default;
    NonCopyable(const NonCopyable&) = delete;
    NonCopyable & operator=(const NonCopyable&) = delete;
};