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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2173746/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 22:23:50  来源:igfitidea点击:

How do I make this C++ object non-copyable?

c++copy-constructornoncopyable

提问by anon

See title.

见标题。

I have:

我有:

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

What need I do from here to make Foo un-copyable?

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

Thanks!

谢谢!

回答by Klaim

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

If you're using boost, you can also inherit from noncopyable : http://www.boost.org/doc/libs/1_41_0/boost/noncopyable.hpp

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

EDIT: C++11 version if you have a compiler supporting this feature:

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

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

回答by Hans Passant

Make the copy constructor and the assignment operator private as well. Just the declaration is enough, you don't have to provide an implementation.

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

回答by Chris H

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

But as Scott Meyers once said..."It's a fine class, it's just that I find the name a bit un, err non natural", or something like that.

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

回答by yesraaj

Just another way to disallow copy constructor,For convenience, a DISALLOW_COPY_AND_ASSIGN macro can be used:

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

Then, in class Foo:

然后,在 Foo 类中:

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

 private:
  DISALLOW_COPY_AND_ASSIGN(Foo);
};

ref from google style sheet

来自谷歌样式表的参考

回答by Matthieu M.

To add a bit there.

在那里补充一点。

The traditional solution is, as has been said, to declareboth Copy Constructorand Assignment Operatoras private, and notto definethem.

传统的解决方案是,正如人们所说的,要宣布双方Copy ConstructorAssignment Operator作为private,而不是定义它们。

  • Because they are private, this will lead to a compile-time errorfrom anyone trying to use them that has not access to the private parts of the class...
  • Which leaves friends (and the class itself) for which the error will occur under the form of undefined symbol, either at link-time(if you check for those there) or most probably at run-time(when trying to load the library).
  • 因为它们是private,这将导致任何尝试使用它们的人都无法访问类的私有部分的编译时错误......
  • 这留下了朋友(和类本身),错误将以 的形式发生undefined symbol,无论是在链接时(如果您检查那里的那些),或者最有可能在运行时(尝试加载库时)。

Of course, it is quite a bother in the second case because you then have to check your code by yourself since you do not have the indication of the file and line at which the error occurs. Fortunately it's limited to your class methods and friends.

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



Also, it is worth noting that these properties are transitive down the inheritance and composition road: the compiler will only generate default versions of the Default Constructor, the Copy Constructor, the Assignment Operatorand the Destructorif it may.

此外,值得注意的是,这些属性在继承和组合过程中是可传递的:编译器将只生成Default ConstructorCopy ConstructorAssignment Operator和 的默认版本,Destructor如果可能的话。

This means that for any of those four, they are automatically generated onlyif they are accessible for all the bases and attributes of the class.

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

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

private:
  Uncopyable(const Uncopyable&);
  Uncopyable& operator=(const Uncopyable&);
};

This is why inheriting from this class (or using it as an attribute) will effectively prevents your own class to be copyable or assignable unless you define those operators yourself.

这就是为什么从此类继承(或将其用作属性)将有效地防止您自己的类可复制或可分配的原因,除非您自己定义这些运算符。

Generally inheritance is chosen over composition there for 2 reasons:

通常选择继承而不是组合有两个原因:

  • The object is effectively Uncopyable, even if polymorphism may not be that useful
  • Inheritance leads to EBOor Empty Base Optimization, while an attribute will be addressable and thus will occupy memory (in each instance of the class) even if it does not actually need it, the compiler has the possibility not to add this overhead for a base class.
  • 该对象是有效的Uncopyable,即使多态性可能没有那么有用
  • 继承导致EBOor Empty Base Optimization,而属性将是可寻址的,因此即使实际上并不需要它也会占用内存(在类的每个实例中),编译器有可能不为基类添加此开销。

You could, alternatively, declare the operators private and not define them in your own class, but the code would be less self-documenting, and you would not be able to automatically search for those class that have this property then (unless you have a full-blown parser).

或者,您可以将运算符声明为私有,而不是在您自己的类中定义它们,但是代码的自我记录性会降低,并且您将无法自动搜索具有此属性的类(除非您有成熟的解析器)。

Hope this shed some light on the mechanism.

希望这对机制有所了解。

回答by bobbaluba

In C++11, you can explicitly disable the creation of default copy and assignment constructor by placing = deleteafter the declaration.

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

From Wikipedia:

来自维基百科

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

The same goes for classes of course.

当然,课程也是如此。

回答by jamesdlin

The typical way to make a C++ object non-copyable is to explicitly declare a copy constructor and copy-assignment operator but not implement them. This will prevent the compiler from generating its own. (Typically this is done in conjunction with declaring them privateso that it generates a compilation error instead of a linker error.)

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

There also is the boost::noncopyableclass that you can inherit from, which does what I described above.

还有boost::noncopyable一个可以继承的类,它执行我上面描述的操作。

回答by Roland Rabien

Make the copy constructor private.

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

Foo(const Foo& src);

You don't need to implement it, just declare it in the header file.

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

回答by Thomas Bonini

This is what I use:

这是我使用的:

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

In your case:

在你的情况下:

struct Example : NoCopy
{
};

回答by Matthieu Brucher

The good practice in C++11 is to declare the copy constructor and assignment as publicly deleted. Not privately deleted, publiclydeleted: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-delete

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