我必须在什么情况下为我的C ++类提供赋值运算符,复制构造函数和析构函数? [重复]

时间:2021-10-31 21:41:47

This question already has an answer here:

这个问题在这里已有答案:

Say I've got a class where the sole data member is something like std::string or std::vector. Do I need to provide a Copy Constructor, Destructor and Assignment Operator?

假设我有一个类,其中唯一的数据成员类似于std :: string或std :: vector。我是否需要提供复制构造函数,析构函数和赋值运算符?

9 个解决方案

#1


12  

In case your class contains only vector/string objects as its data members, you don't need to implement these. The C++ STL classes (like vector, string) have their own copy ctor, overloaded assignment operator and destructor.

如果您的类仅包含矢量/字符串对象作为其数据成员,则无需实现这些。 C ++ STL类(如vector,string)有自己的copy ctor,重载赋值运算符和析构函数。

But in case if your class allocates memory dynamically in the constructor then a naive shallow copy will lead to trouble. In that case you'll have to implement copy ctor, overloaded assignment operator and destructor.

但是如果你的类在构造函数中动态分配内存,那么一个天真的浅拷贝将导致麻烦。在这种情况下,您将必须实现copy ctor,重载赋值运算符和析构函数。

#2


5  

The usual rule of thumb says: if you need one of them, then you need them all.

通常的经验法则是:如果你需要其中一个,那么你需要它们。

Not all classes need them, though. If you class holds no resources (memory, most notably), you'll be fine without them. For example, a class with a single string or vector constituent doesn't really need them - unless you need some special copying behavior (the default will just copy over the members).

但并非所有课程都需要它们。如果你的班级没有资源(记忆,最值得注意的是),没有它们你就没事了。例如,具有单个字符串或向量成分的类并不真正需要它们 - 除非您需要一些特殊的复制行为(默认只会复制成员)。

#3


4  

The default copy constructor will copy the vector if it is declared by value. Beware if you stored pointers in your vector, in such a case, you need to provide specific behaviour for copy/assignement/destruction to avoid memory leaks or multiple delete.

如果向量是按值声明的,则默认复制构造函数将复制该向量。请注意,如果在向量中存储指针,在这种情况下,您需要提供复制/分配/销毁的特定行为,以避免内存泄漏或多次删除。

#4


3  

I can think of a few cases when you need to write your own Big Three. All standard containers know how to copy and destroy themselves, so you don't necessarily need to write them. Here's how to know when you do:

当你需要写自己的三巨头时,我可以想到几个案例。所有标准容器都知道如何复制和销毁自己,因此您不一定需要编写它们。以下是知道您何时做的事情:

Does my class own any resources?

我的班级是否拥有任何资源?

The default copy semantics for pointers is to copy the value of the pointer, not what it points to. If you need to deep copy something, even if it's stored inside a standard container, you need to write your own copy constructor and assignment operator. You also need to write your own destructor to properly free those resources.

指针的默认复制语义是复制指针的值,而不是它指向的值。如果您需要深层复制某些内容,即使它存储在标准容器中,您也需要编写自己的复制构造函数和赋值运算符。您还需要编写自己的析构函数以正确释放这些资源。

Might someone inherit from my class?

有人可以从我的班级继承吗?

Base classes need a destructor. Herb Sutter recommends making them either public and virtual (most common case) or protected and non-virtual, depending on what you want to do with them. The compiler-generated destructor is public and non-virtual, so you'll have to write your own, even if it doesn't have any code in it. (Note: this doesn't imply you have to write a copy constructor or assignment operator.)

基类需要析构函数。 Herb Sutter建议将它们设置为公共和虚拟(最常见的情况)或受保护和非虚拟,具体取决于您要对它们执行的操作。编译器生成的析构函数是公共的和非虚拟的,所以你必须编写自己的析构函数,即使它没有任何代码。 (注意:这并不意味着您必须编写复制构造函数或赋值运算符。)

Should I prevent a user from copying objects of my class?

我应该阻止用户复制我班级的对象吗?

If you don't want the user to copy your objects (maybe that's too expensive), you need to declare the copy constructor and assignment operators either protected or private. You don't have to implement them unless you need them. (Note: this doesn't imply you have to write a destructor.)

如果您不希望用户复制您的对象(可能太贵),您需要声明复制构造函数和赋值运算符是受保护的还是私有的。除非您需要,否则不必实施它们。 (注意:这并不意味着你必须编写析构函数。)

Bottom line:

The most important thing is to understand what the compiler-generated copy constructor, assignment operator, and destructor will do. You don't need to be afraid of them, but you need to think about them and decide if their behavior is appropriate for your class.

最重要的是要了解编译器生成的复制构造函数,赋值运算符和析构函数将执行的操作。你不需要害怕它们,但你需要考虑它们并决定它们的行为是否适合你的班级。

#5


2  

No but there are a number of reasons why you shouldn't allow the compiler to auto generate these functions.

不,但是有很多原因导致您不应该允许编译器自动生成这些函数。

In my experience it is always best to define them yourself, and to get into the habit of making sure that they are maintained when you change the class. Firstly you may well want to put a breakpoint on when a particular ctor or dtor is called. Also not defining them can result in code bloat as the compiler will generate inline calls to member ctor and dtor (Scott Meyers has a section on this).

根据我的经验,最好自己定义它们,并养成在改变课程时确保维护它们的习惯。首先,您可能希望在调用特定ctor或dtor时设置断点。同样没有定义它们会导致代码膨胀,因为编译器将生成对成员ctor和dtor的内联调用(Scott Meyers有一节关于此)。

Also you sometimes want to disallow the default copy ctors and assignments. For example I have an application that stores and manipulates very large blocks of data. We routinely have the equivalent of an STL vector holding millions of 3D points and it would be a disaster if we allowed those containers to be copy constructed. So the ctor and assignment operators are declared private and not defined. That way if anyone writes

此外,您有时也想禁止默认复制和分配。例如,我有一个存储和操作非常大的数据块的应用程序。我们通常具有相当于容纳数百万个3D点的STL向量,如果我们允许这些容器被复制构造,那将是一场灾难。因此ctor和赋值运算符被声明为私有而未定义。这样,如果有人写

class myClass {
  void doSomething(const bigDataContainer data); // not should be passed by reference
}

then they'll get a compiler error. Our experience is that an explicit become() or clone() method is far less error prone.

然后他们会得到一个编译器错误。我们的经验是,显式的()或clone()方法更不容易出错。

So all in all there are many reason to avoid auto generated compiler functions.

总而言之,有许多理由避免自动生成的编译器功能。

#6


1  

those container will need a "copy constructible" element, and if you don't supply the copy constructor, it will call default copy constructor of your class by deducing from your class members (shallow copy).

这些容器需要一个“copy constructible”元素,如果你不提供拷贝构造函数,它将通过从你的类成员中推导出来调用你的类的默认拷贝构造函数(浅拷贝)。

easy explanation about default copy constructor is here : http://www.fredosaurus.com/notes-cpp/oop-condestructors/copyconstructors.html

有关默认复制构造函数的简单说明,请访问:http://www.fredosaurus.com/notes-cpp/oop-condestructors/copyconstructors.html

it is so with destructor, the container need to have access to your destructor or your default class destructor if you don't provides one (ie. it will not work if you declare your destructor as private )

如果您没有提供析构函数,那么容器需要访问您的析构函数或默认类析构函数(即,如果您将析构函数声明为私有,它将无法工作)

#7


0  

you need to provide them if you need them. or possible users of your classes. destructor is always a must, and copy constructors and assignment operator are automatically created by compiler. (MSVC at least)

如果需要,你需要提供它们。或者您的课程的可能用户。析构函数始终是必需的,复制构造函数和赋值运算符由编译器自动创建。 (MSVC至少)

#8


0  

When ever you have a class that requires deep copies, you should define them.

当你有一个需要深拷贝的类时,你应该定义它们。

Specifically, any class which contains pointers or references should contain them such as:

具体来说,任何包含指针或引用的类都应包含它们,例如:

class foo {
private:
    int a,b;
    bar *c;
}

Subjectively, I would say always define them, as the default behavior provided by the compiler generated version may not be what you expect / want.

主观上,我会说总是定义它们,因为编译器生成的版本提供的默认行为可能不是您期望/想要的。

#9


0  

Not for strings or vectors, since the trivial constructors / destructors etc, will do fine.

不是字符串或向量,因为琐碎的构造函数/析构函数等,会很好。

If your class has pointers to other data and need deep copies, or if your class holds a resource that has to be deallocated or has to be copied in a special way.

如果您的类具有指向其他数据的指针并需要深层副本,或者您的类拥有必须取消分配或必须以特殊方式复制的资源。

#1


12  

In case your class contains only vector/string objects as its data members, you don't need to implement these. The C++ STL classes (like vector, string) have their own copy ctor, overloaded assignment operator and destructor.

如果您的类仅包含矢量/字符串对象作为其数据成员,则无需实现这些。 C ++ STL类(如vector,string)有自己的copy ctor,重载赋值运算符和析构函数。

But in case if your class allocates memory dynamically in the constructor then a naive shallow copy will lead to trouble. In that case you'll have to implement copy ctor, overloaded assignment operator and destructor.

但是如果你的类在构造函数中动态分配内存,那么一个天真的浅拷贝将导致麻烦。在这种情况下,您将必须实现copy ctor,重载赋值运算符和析构函数。

#2


5  

The usual rule of thumb says: if you need one of them, then you need them all.

通常的经验法则是:如果你需要其中一个,那么你需要它们。

Not all classes need them, though. If you class holds no resources (memory, most notably), you'll be fine without them. For example, a class with a single string or vector constituent doesn't really need them - unless you need some special copying behavior (the default will just copy over the members).

但并非所有课程都需要它们。如果你的班级没有资源(记忆,最值得注意的是),没有它们你就没事了。例如,具有单个字符串或向量成分的类并不真正需要它们 - 除非您需要一些特殊的复制行为(默认只会复制成员)。

#3


4  

The default copy constructor will copy the vector if it is declared by value. Beware if you stored pointers in your vector, in such a case, you need to provide specific behaviour for copy/assignement/destruction to avoid memory leaks or multiple delete.

如果向量是按值声明的,则默认复制构造函数将复制该向量。请注意,如果在向量中存储指针,在这种情况下,您需要提供复制/分配/销毁的特定行为,以避免内存泄漏或多次删除。

#4


3  

I can think of a few cases when you need to write your own Big Three. All standard containers know how to copy and destroy themselves, so you don't necessarily need to write them. Here's how to know when you do:

当你需要写自己的三巨头时,我可以想到几个案例。所有标准容器都知道如何复制和销毁自己,因此您不一定需要编写它们。以下是知道您何时做的事情:

Does my class own any resources?

我的班级是否拥有任何资源?

The default copy semantics for pointers is to copy the value of the pointer, not what it points to. If you need to deep copy something, even if it's stored inside a standard container, you need to write your own copy constructor and assignment operator. You also need to write your own destructor to properly free those resources.

指针的默认复制语义是复制指针的值,而不是它指向的值。如果您需要深层复制某些内容,即使它存储在标准容器中,您也需要编写自己的复制构造函数和赋值运算符。您还需要编写自己的析构函数以正确释放这些资源。

Might someone inherit from my class?

有人可以从我的班级继承吗?

Base classes need a destructor. Herb Sutter recommends making them either public and virtual (most common case) or protected and non-virtual, depending on what you want to do with them. The compiler-generated destructor is public and non-virtual, so you'll have to write your own, even if it doesn't have any code in it. (Note: this doesn't imply you have to write a copy constructor or assignment operator.)

基类需要析构函数。 Herb Sutter建议将它们设置为公共和虚拟(最常见的情况)或受保护和非虚拟,具体取决于您要对它们执行的操作。编译器生成的析构函数是公共的和非虚拟的,所以你必须编写自己的析构函数,即使它没有任何代码。 (注意:这并不意味着您必须编写复制构造函数或赋值运算符。)

Should I prevent a user from copying objects of my class?

我应该阻止用户复制我班级的对象吗?

If you don't want the user to copy your objects (maybe that's too expensive), you need to declare the copy constructor and assignment operators either protected or private. You don't have to implement them unless you need them. (Note: this doesn't imply you have to write a destructor.)

如果您不希望用户复制您的对象(可能太贵),您需要声明复制构造函数和赋值运算符是受保护的还是私有的。除非您需要,否则不必实施它们。 (注意:这并不意味着你必须编写析构函数。)

Bottom line:

The most important thing is to understand what the compiler-generated copy constructor, assignment operator, and destructor will do. You don't need to be afraid of them, but you need to think about them and decide if their behavior is appropriate for your class.

最重要的是要了解编译器生成的复制构造函数,赋值运算符和析构函数将执行的操作。你不需要害怕它们,但你需要考虑它们并决定它们的行为是否适合你的班级。

#5


2  

No but there are a number of reasons why you shouldn't allow the compiler to auto generate these functions.

不,但是有很多原因导致您不应该允许编译器自动生成这些函数。

In my experience it is always best to define them yourself, and to get into the habit of making sure that they are maintained when you change the class. Firstly you may well want to put a breakpoint on when a particular ctor or dtor is called. Also not defining them can result in code bloat as the compiler will generate inline calls to member ctor and dtor (Scott Meyers has a section on this).

根据我的经验,最好自己定义它们,并养成在改变课程时确保维护它们的习惯。首先,您可能希望在调用特定ctor或dtor时设置断点。同样没有定义它们会导致代码膨胀,因为编译器将生成对成员ctor和dtor的内联调用(Scott Meyers有一节关于此)。

Also you sometimes want to disallow the default copy ctors and assignments. For example I have an application that stores and manipulates very large blocks of data. We routinely have the equivalent of an STL vector holding millions of 3D points and it would be a disaster if we allowed those containers to be copy constructed. So the ctor and assignment operators are declared private and not defined. That way if anyone writes

此外,您有时也想禁止默认复制和分配。例如,我有一个存储和操作非常大的数据块的应用程序。我们通常具有相当于容纳数百万个3D点的STL向量,如果我们允许这些容器被复制构造,那将是一场灾难。因此ctor和赋值运算符被声明为私有而未定义。这样,如果有人写

class myClass {
  void doSomething(const bigDataContainer data); // not should be passed by reference
}

then they'll get a compiler error. Our experience is that an explicit become() or clone() method is far less error prone.

然后他们会得到一个编译器错误。我们的经验是,显式的()或clone()方法更不容易出错。

So all in all there are many reason to avoid auto generated compiler functions.

总而言之,有许多理由避免自动生成的编译器功能。

#6


1  

those container will need a "copy constructible" element, and if you don't supply the copy constructor, it will call default copy constructor of your class by deducing from your class members (shallow copy).

这些容器需要一个“copy constructible”元素,如果你不提供拷贝构造函数,它将通过从你的类成员中推导出来调用你的类的默认拷贝构造函数(浅拷贝)。

easy explanation about default copy constructor is here : http://www.fredosaurus.com/notes-cpp/oop-condestructors/copyconstructors.html

有关默认复制构造函数的简单说明,请访问:http://www.fredosaurus.com/notes-cpp/oop-condestructors/copyconstructors.html

it is so with destructor, the container need to have access to your destructor or your default class destructor if you don't provides one (ie. it will not work if you declare your destructor as private )

如果您没有提供析构函数,那么容器需要访问您的析构函数或默认类析构函数(即,如果您将析构函数声明为私有,它将无法工作)

#7


0  

you need to provide them if you need them. or possible users of your classes. destructor is always a must, and copy constructors and assignment operator are automatically created by compiler. (MSVC at least)

如果需要,你需要提供它们。或者您的课程的可能用户。析构函数始终是必需的,复制构造函数和赋值运算符由编译器自动创建。 (MSVC至少)

#8


0  

When ever you have a class that requires deep copies, you should define them.

当你有一个需要深拷贝的类时,你应该定义它们。

Specifically, any class which contains pointers or references should contain them such as:

具体来说,任何包含指针或引用的类都应包含它们,例如:

class foo {
private:
    int a,b;
    bar *c;
}

Subjectively, I would say always define them, as the default behavior provided by the compiler generated version may not be what you expect / want.

主观上,我会说总是定义它们,因为编译器生成的版本提供的默认行为可能不是您期望/想要的。

#9


0  

Not for strings or vectors, since the trivial constructors / destructors etc, will do fine.

不是字符串或向量,因为琐碎的构造函数/析构函数等,会很好。

If your class has pointers to other data and need deep copies, or if your class holds a resource that has to be deallocated or has to be copied in a special way.

如果您的类具有指向其他数据的指针并需要深层副本,或者您的类拥有必须取消分配或必须以特殊方式复制的资源。