移动语义只是一个浅拷贝并将其他指针设置为空吗?

Posted

技术标签:

【中文标题】移动语义只是一个浅拷贝并将其他指针设置为空吗?【英文标题】:Is move semantics just a shallow copy and setting other's pointers to null? 【发布时间】:2017-05-16 09:34:52 【问题描述】:

我一直在阅读 C++ 中的移动语义,在解释中人们给出了很多类比来帮助简化它,在我的脑海中,我所能看到的是人们所说的“移动”而不是“复制” " 只是对象的浅表副本,并将“移出”对象中的任何指针设置为 null。这基本上是要点吗?浅拷贝并将其他指针设为null?

【问题讨论】:

差不多了。你明白为什么这样做完全没问题吗? 好吧,因为在 C 和 C++ 中删除空指针是完全安全的(我检查过),并且当“移出”对象被销毁时,您不会两次销毁资源。我只是在为所有这些新的 C++ 东西而苦苦挣扎。 这不仅仅是需要删除的指针。它是关于一般资源(例如线程、文件句柄、数据库连接......) 【参考方案1】:

浅拷贝并将其他指针设置为空?

浅拷贝 - 是的。将其他指针设置为 null - 并非总是如此。

最低要求是被移动的对象处于“未定义但有效的状态”,也就是说您可以重新分配给它,再次移动它或删除它而不会导致程序失败,但不执行其他状态相关的操作就可以了。这意味着在std::swap 方面实现移动分配通常是完全有效的。

一些对象定义了更强的契约。其中之一是std::unique_ptr。从其中之一移动将导致它包含null,但这已明确记录在案。

【讨论】:

【参考方案2】:

移动语义只是一个浅拷贝并将其他指针设置为空吗?

如果指针为空满足类不变量,则可以。也就是:如果带有空指针的对象是有效状态。

所以,我再给个长一点的描述:移动构造函数和赋值运算符执行一个浅拷贝,并将移动的对象清理成满足类不变量的状态。

还请记住,在移动赋值的情况下,您必须记住处理将被燕子副本覆盖的指针。

例如,如果类拥有指向对象,则不变量要求没有两个对象拥有同一个对象。至少有三种方法可以实现:

将指针设为空 构造一个新对象 将指针与移动到的对象交换(在移动构造函数的情况下,这与前面的选项之一基本相同,因为指针最初是未初始化的,除非首先执行前面的一个,但使用移动赋值可以轻松完成照顾移动到的对象先前指向的对象)。

如果不变量需要,有时还需要设置非资源数据,例如size 字段或类似字段以匹配对象的新状态。除了拥有指向内存的指针(例如文件描述符)之外,该对象还可能拥有其他资源,并且还必须清理这些资源。

【讨论】:

以上是关于移动语义只是一个浅拷贝并将其他指针设置为空吗?的主要内容,如果未能解决你的问题,请参考以下文章

iOS 集合的深复制与浅复制

C++ 浅拷贝 & 深拷贝

深拷贝/浅拷贝

深拷贝/浅拷贝

python变量存储,理解赋值浅拷贝深拷贝

深拷贝 与 浅拷贝