提问人:anon 提问时间:2/1/2010 最后编辑:Vertexwahnanon 更新时间:5/3/2023 访问量:76865
如何使此 C++ 对象不可复制?
How do I make this C++ object non-copyable?
问:
请参阅标题。
我有:
class Foo {
private:
Foo();
public:
static Foo* create();
}
我需要做些什么才能使 Foo 不可复制?
答:
将复制构造函数设为私有。
Foo(const Foo& src);
您不需要实现它,只需在头文件中声明它即可。
将复制构造函数和赋值运算符也设为私有。只需声明就足够了,您不必提供实现。
使 C++ 对象不可复制的典型方法是显式声明复制构造函数和复制赋值运算符,但不实现它们。这将阻止编译器生成自己的编译器。(通常,这与声明它们一起完成,以便生成编译错误而不是链接器错误。private
还有一个 boost::noncopyable
类,你可以从中继承,它执行我上面描述的。
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
评论
#include <boost/utility.hpp>
class Foo : boost::noncopyable {...
但正如斯科特·迈耶斯(Scott Meyers)曾经说过的那样......“这是一门很好的课,只是我觉得这个名字有点不自然,不自然”,或者类似的东西。
评论
在那里添加一点。
如前所述,传统的解决方案是同时声明 和 作为,而不是定义它们。Copy Constructor
Assignment Operator
private
- 因为它们是 ,这将导致任何试图使用它们的人无法访问类的私有部分的编译时错误......
private
- 这留下了朋友(和类本身),其错误将以 的形式发生,要么在链接时(如果您在那里检查那些),要么很可能在运行时(尝试加载库时)。
undefined symbol
当然,在第二种情况下,这很麻烦,因为您必须自己检查代码,因为您没有发生错误的文件和行的指示。幸运的是,它仅限于您的课程方法和朋友。
此外,值得注意的是,这些属性在继承和组合过程中是可传递的:编译器只会生成 、 、 和 的默认版本(如果可能的话)。Default Constructor
Copy Constructor
Assignment Operator
Destructor
这意味着,对于这四个中的任何一个,只有当它们可供类的所有基和属性访问时,它们才会自动生成。
// What does boost::noncopyable looks like >
class Uncopyable {
public:
Uncopyable() {}
private:
Uncopyable(const Uncopyable&);
Uncopyable& operator=(const Uncopyable&);
};
这就是为什么从这个类继承(或将其用作属性)将有效地阻止你自己的类可复制或可赋值,除非你自己定义这些运算符。
一般来说,选择继承而不是组合有两个原因:
- 对象是有效的,即使多态性可能没有那么有用
Uncopyable
- 继承导致 或 ,虽然属性是可寻址的,因此即使它实际上并不需要它,也会占用内存(在类的每个实例中),但编译器有可能不为基类添加此开销。
EBO
Empty Base Optimization
或者,您可以声明运算符是私有的,而不是在自己的类中定义它们,但代码的自记录性会降低,并且您将无法自动搜索具有此属性的类(除非您有一个成熟的解析器)。
希望这能对机制有所启发。
评论
Uncopyable
这是我使用的:
/* 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
{
};
评论
只是另一种禁止复制构造函数的方法,为了方便起见,可以使用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);
};
评论
在 C++ 11 中,可以通过在声明后放置来显式禁用默认复制和赋值构造函数的创建。= delete
来自维基百科:
struct NonCopyable {
NonCopyable() = default;
NonCopyable(const NonCopyable&) = delete;
NonCopyable & operator=(const NonCopyable&) = delete;
};
当然,课程也是如此。
C++ 11 中的良好做法是将复制构造函数和赋值声明为公开删除。 未私下删除、公开删除:https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-delete
上一个:禁用复制构造函数
评论