在什么情况下我必须为我的 C++ 提供赋值运算符、复制构造函数和析构函数?班级?

发布于 2024-08-24 04:05:57 字数 104 浏览 5 评论 0原文

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

回忆凄美了谁 2024-08-31 04:05:57

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

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

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.

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.

与往事干杯 2024-08-31 04:05:57

通常的经验法则是:如果您需要其中之一,那么您就需要全部。

但并非所有课程都需要它们。如果你的类没有资源(尤其是内存),那么没有它们也没关系。例如,具有单个 stringvector 组成部分的类并不真正需要它们 - 除非您需要一些特殊的复制行为(默认情况下只会复制成员) 。

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).

阳光的暖冬 2024-08-31 04:05:57

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

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.

世界如花海般美丽 2024-08-31 04:05:57

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

我的班级拥有任何资源吗?

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

有人可以继承我的类吗?

基类需要析构函数。 Herb Sutter 建议将它们设为 public虚拟(最常见的情况)或受保护和非虚拟,具体取决于您想用它们做什么。编译器生成的析构函数是公共的且非虚拟的,因此您必须编写自己的析构函数,即使其中没​​有任何代码。 (注意:这并不意味着您必须编写复制构造函数或赋值运算符。

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

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

底线:

最重要的是了解编译器生成的复制构造函数、赋值运算符是什么,和析构函数就可以了。你不需要害怕他们,但你需要考虑他们并决定他们的行为是否适合你的班级。

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.)

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.

长途伴 2024-08-31 04:05:57

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

根据我的经验,最好自己定义它们,并养成在更改类时确保它们得到维护的习惯。首先,您可能希望在调用特定 ctor 或 dtor 时放置一个断点。另外,不定义它们可能会导致代码膨胀,因为编译器将生成对成员 ctor 和 dtor 的内联调用(Scott Meyers 有一节介绍了这一点)。

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

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

,他们就会收到编译器错误。我们的经验是,显式的become()或clone()方法更不容易出错。

总而言之,有很多理由避免自动生成的编译器函数。

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).

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

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.

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

仙气飘飘 2024-08-31 04:05:57

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

关于默认复制构造函数的简单解释在这里: http://www.fredosaurus .com/notes-cpp/oop-condestructors/copyconstructors.html

析构函数也是如此,如果您不提供析构函数或默认类析构函数,容器需要访问您的析构函数(即它将如果您将析构函数声明为私有,则不起作用)

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).

easy explanation about default copy constructor is here : 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 )

情绪操控生活 2024-08-31 04:05:57

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

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)

逐鹿 2024-08-31 04:05:57

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

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

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

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

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.

魂归处 2024-08-31 04:05:57

不适用于字符串或向量,因为简单的构造函数/析构函数等就可以了。

如果您的类具有指向其他数据的指针并且需要深层复制,或者您的类拥有必须释放或必须以特殊方式复制的资源。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文