Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

定义了析构函数,就必须删除移动构造函数、移动赋值函数、拷贝构造函数、拷贝赋值函数? #83

Open
agetu opened this issue Feb 8, 2025 · 6 comments

Comments

@agetu
Copy link

agetu commented Feb 8, 2025

深入理解析构函数与生命周期中
定义了析构函数,就必须删除移动构造函数、移动赋值函数、拷贝构造函数、拷贝赋值函数
根据三五法则,不应该是同时定义剩下的拷贝构造函数、拷贝赋值函数或者移动构造函数、移动赋值函数、拷贝构造函数、拷贝赋值函数吗?为什么是删除呢

@archibate
Copy link
Contributor

有些持有“资源”的类,根本就没法定义拷贝构造函数,必须删除。
比如一个进程句柄,如何支持拷贝构造?难道进程句柄拷贝的时候要把底层的进程自动fork一份出来?(做不到的)
一些可以拷贝的资源,比如vector持有的内存资源,可以定义出拷贝构造函数来。
可见并不是所有带有析构函数的类都需要“定义”四大函数,实际上大部分概率都是需要“删除”的,很少有能拷贝的资源,能拷贝的基本上都是STL容器,这些标准库帮你实现好了,用户很少需要自己手搓容器,大部分用户需要自定义析构函数的情况都是不可拷贝的资源类,这也是我强调你定义析构函数的第一件事是删四大函数的初衷。

把一个可以拷贝的资源类,删除四大函数,也不会有错。
把一个本来需要删除四大函数的资源类,定义了四大函数,那就出错了。
根据“忘记导向安全”原则,我必须先大声抛出一个正确的答案,防止记忆错乱。
反正,先删掉肯定不会有错,等需要了再加上。

所以是我说的有点问题,准确的来说应该是:

定义了析构函数,就必须 删除 或 自定义 移动构造函数、移动赋值函数、拷贝构造函数、拷贝赋值函数

就好比专业的律师会告诉你:插座里如果没有电,那么可以用手摸;插座里如果有电,那就不能用手摸。
律师句子太长,你容易记忆混淆,一糊涂就摸上去了,一摸就没命了。
而我会先大声叫出:不允许用手摸插座。
先让你产生插座是危险的第一印象,之后等你需要修理插座时,再告诉你可以先断电再操作,也不迟。

更糟糕的是,它们官方律师口中的“定义”实际上包含“删除”,就官方话术中,“删除”也是定义的一种,搞笑吧。
它们随口一说官方花束信息差打满伤害,你不知道“删除”也是“定义”的一种,误以为有析构函数就必须“定义”四大函数而不能“删除”了,然而现实中90%的情况都是需要删除四大函数!
这就很误导人,就好比脑瘫电工书籍上说“可以用手摸插座”,然后辩解称“戴着香蕉手套的手也是手,所以可以用手摸带电的插座”一样可笑,让人不意识到插座90%情况下是不能手摸的。

@KollerWithDoris
Copy link

KollerWithDoris commented Feb 23, 2025 via email

@frederick-vs-ja
Copy link
Contributor

“定义”一词包含的情况很多。我们是否该用更通俗的“手写函数体”来避免误解?

@sweet2honey
Copy link

“定义”一词包含的情况很多。我们是否该用更通俗的“手写函数体”来避免误解?

我觉得“手写函数体”更是一个容易混淆的描述,=default 这种我算手写了吗?

定义了析构函数,就必须 删除 或 自定义 移动构造函数、移动赋值函数、拷贝构造函数、拷贝赋值函数

这里我觉得小彭老师想说是“自定义了析构函数”的意思吧?想要表达的核心思想是当一个类持有需要在析构过程中额外手动处理的资源,那么这个类大概率不能被简单地执行赋值、拷贝等操作,所以从安全的原则上来看,先一杆子打死把这四个函数全给删除了(后面描述改成了删除或自定义),用到再加。

@frederick-vs-ja
Copy link
Contributor

“定义”一词包含的情况很多。我们是否该用更通俗的“手写函数体”来避免误解?

我觉得“手写函数体”更是一个容易混淆的描述,=default 这种我算手写了吗?

不算。(莫非我们居然没有一个简单的词组描述“手写花括号函数体”吗?)

@sweet2honey
Copy link

“定义”一词包含的情况很多。我们是否该用更通俗的“手写函数体”来避免误解?

我觉得“手写函数体”更是一个容易混淆的描述,=default 这种我算手写了吗?

不算。(莫非我们居然没有一个简单的词组描述“手写花括号函数体”吗?)

这确实是我比较讨厌 C++ 的一个点,“定义”在标准里面是通过黑名单式地这么说:

Every declaration is a definition, except for the following: ....
(我也很讨厌做语言律师啊)

你说的这个“花括号函数体”也是个不错的描述吧。
但是析构 =delete 又被解释为 Disabling the implicit destructor.,也算定义,见鬼了。小彭老师这种一杆子打死的做法还真是绝大多数情况下比较粗暴有效的解法。
麻了定义词汇真多 啊啊啊草每天想爆干 C++ 一百遍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants