安全到标准:移动会员?
Safe to std:move a member?
已经找到了类似的问题,但不完全是这种情况。 以以下代码为例:
#include <iostream>
#include <string>
#include <vector>
struct Inner
{
int a, b;
};
struct Outer
{
Inner inner;
};
std::vector<Inner> vec;
int main()
{
Outer * an_outer = new Outer;
vec.push_back(std::move(an_outer->inner));
delete an_outer;
}
这安全吗?即使这些是多态类或具有自定义析构函数的类?
我关注的是"Outer
"的实例,它有一个成员变量"inner
"移走了。据我所知,移动的东西不应该再被碰了。但是,这是否包括应用于outer
的删除调用,并且在技术上也会调用inner
上的删除(从而"触摸"它(?
std::move
和更一般的移动语义都不会对对象模型产生任何影响。它们不会阻止对象存在,也不会阻止您将来使用这些对象。
他们所做的是要求从你"移动"的东西中借用封装的资源。例如,一个vector
,它直接只存储指针一些动态分配的数据:该数据的所有权概念可以通过简单地复制该指针然后告诉vector
将指针清空并且不再与该数据有任何关系来"窃取"。它屈服了。数据现在属于您。你有存在于宇宙中的最后一个指向它的指针。
所有这些都是通过一堆黑客实现的。第一个是std::move
,它只是将您的vector
表达式转换为vector&&
,因此当您将其结果传递给构造或赋值操作时,将触发采用vector&&
的版本(移动构造函数或移动赋值运算符(而不是采用const vector&
的版本,并且该版本执行执行我在上一段中描述的操作所需的步骤。
(对于我们制作的其他类型的产品,我们传统上一直遵循这种模式,因为这样我们才能拥有好东西并说服人们使用我们的库。
但是你仍然可以使用矢量!你可以"触摸"它。你可以用它做什么可以从vector
文档中找到,这延伸到任何其他可移动类型:对你使用移动对象的约束完全取决于它的类型,以及设计该类型的人所做的决定。
这些都对vector
的生命周期没有任何影响。它仍然存在,它仍然需要记忆,到时候它仍然会被破坏。(在此特定示例中,您实际上可以.clear()
它并重新开始将数据添加到新缓冲区。
因此,即使int
对此有任何概念(他们没有;他们没有封装间接存储的数据,也没有资源;他们没有构造函数,所以他们也没有构造函数接受int&&
(,"接触"它们delete
将是完全安全的。而且,更一般地说,这些都不取决于您移动的东西是否是会员。
更一般地说,如果你有一个类型T
,以及一个该类型的对象,并且你从它移动,并且T
的约束之一是你在从它移动后无法delete
它,那将是T
中的一个错误。这将是T
作者的一个严重错误。您的对象都需要是可破坏的。该错误可能表现为编译失败,或者更有可能表现为未定义的行为,具体取决于错误到底是什么。
tl;大卫:是的,这是安全的,有几个原因。
std::move
是对右值引用的强制转换,它主要更改选择的构造函数/赋值运算符重载。在您的示例中,移动构造函数是默认生成的移动构造函数,它只是复制ints
,因此不会发生任何事情。
这通常是否安全取决于您的类实现移动构造/分配的方式。例如,假设您的类持有一个指针。您必须将其设置为在移自类中nullptr
,以避免在移自类被销毁时销毁指向的数据。
因为仅仅定义移动语义是一种自定义方式几乎总是会导致问题,所以五法则表示,如果您自定义以下任何一种:
- 复制构造函数
- 复制赋值运算符
- 移动构造函数
- 移动赋值运算符
- 析构函数
您通常应该自定义所有内容,以确保它们的行为与呼叫者通常对您的班级的期望一致。
- 安全到标准:移动会员?
- 移动后是否需要重置标准::列表?
- 返回标准::移动(m_field)还是返回m_field?
- 视觉理解移动C++标准的语义
- 从标准容器中移动元素是否合法?
- 将旧版C++标准库从GNU版本移动到LLVM版本中的版本
- 标准::移动"in-place operation"
- 在C++标准中移动概念
- 标准是否保证在移动std::p ackaged_task后安全使用std::future?
- 为什么标准在移动分配运算符中使用交换?
- 无法移动标准::任何
- 标准::atomic_应该如何...<std::shared_ptr>用于线程安全类的复制和移动操作?
- C++标准::移动指针
- Visual Studio 2012 是否正确执行此操作?标准::移动
- 移动分配与标准复制和交换不兼容
- 复制与标准::移动整数
- 是否有将范围移动到矢量中的标准方法
- 标准::移动和映射分配
- C++11 GCC 4.6.2标准::移动
- 标准::移动 - 标准::内部指针