移动构造函数的后置条件是什么
What is the post condition of a move constructor?
考虑一个类:
class foo {
public:
foo(foo &&rhs) { /* some code */ }
~foo() noexcept { /* code that does destruction of owning objects */ }
private:
/* some non-trivial pointer graph like structure */
};
假设:
{
foo &f = get_from_other_class();
foo g = std::move(f);
// some time later f goes our of scope or the owning object is destroyed.
}
执行std::move(f)
后,哪些职位条件适用于f
?
注意
我怀疑f
必须仍然是干净的可破坏的(不破坏拥有g
的内容(,但我在 C++11 标准中没有找到相应的引用。我正在浏览 12.8 复制和移动类对象。
每个对象都必须是可破坏的,除非你只动态分配它。在被"移出"之后,即将其值绑定到右值引用(例如移动构造函数的第一个参数(,对象仍然需要有效且可破坏,但通常它可以处于"未指定"状态,您根本不应该再查看该对象并让它超出范围或重新分配它。
某些类型提供了更强的保证,例如std::unique_ptr
承诺在移动构造时,它将移出对象保留在等于 nullptr
的状态。
和右值引用背后的一般思想是,右值的对象不应具有别名,具体而言,当对象绑定到右值引用时,该对象没有其他别名。标准库对其公开的右值引用接口做出这些假设。
后置条件是移自对象处于未指定但有效的状态。正是如此:它是未指定的,这意味着只要它是有效的,它就可以是你选择它(或库实现者(的任何内容。
在执行 std::move(f( 之后,哪些后置条件适用于 f?
这在很大程度上可以由foo
的作者决定,但也受到对foo
提出要求的算法(std与否(的约束。
许多算法将要求在其移自状态下foo
Destructible
并可以为其分配新值。 但这取决于使用foo
的上下文。
如果foo
与 std 库组件一起使用,则要求由表 20 -- MoveConstructible 要求规定:
RV 的状态未指定 [ 注:RV 仍需满足要求 使用它的库组合。中列出的操作 无论 RV 是否已移动,这些要求必须按照指定的方式工作 从或不从。
例如:假设您用vector<foo>
调用std::sort
。 std::sort
需要foo
:Swappable
、MoveConstructible
、Destructible
、MoveAssignable
和LessThanComparable
。
std::sort
将这些要求放在foo
foo
是否处于移出状态。
严格来说,如果与std::sort
一起使用,则在处于移自状态时不需要foo
LessThanComparable
。 实现者比较移自对象是没有意义的,因为它的值未指定。 尽管如此,C++11和C++14标准目前要求LessThanComparable
。 结果不需要是合理的,但要求在执行时不会崩溃。 未来的标准可能会放宽这一要求,但谁知道呢。
因此,总而言之,foo
的作者可以说明允许对移自foo
执行哪些操作。
任何算法都可以说明它对它所操作的类型的要求。
在foo
满足算法要求的交叉点中,代码起作用。 C++标准不考虑移出状态特殊。
表 20 (§ 17.6.3.1( 定义了 MoveConstructible 要求:
+------------+----------------------------------------------------------------+|表达式 | 后置条件 |+------------+----------------------------------------------------------------+|T u = rv; |U相当于建造前房车的价值 ||T(房车( |T(rv( 相当于施工前 rv 的值 |+------------+----------------------------------------------------------------+
rv 的状态未指定 [ 注意:rv 仍必须满足 使用它的库组件的要求。这 这些要求中列出的操作必须按指定工作,无论是否 房车是否已移出。
该注释指出,根据@Kerrek的回答,库组件可能有不同的要求。
移自对象必须准备好运行析构函数。
Per Stroustrup, C++ Programming Language, 4th Edition 2014
如果 x 被移出,x 将具有"一些移出状态"......
"对于最有趣的案例,容器, 移出状态为"空"...
我倾向于认为它类似于默认的初始化变量。
内置类型的值在移动后保持不变。
default moved-from state
是默认析构函数和默认复制赋值正常工作的。
其中一个定义是,如果析构函数运行,以前由对象管理的任何资源将不再由对象管理;析构函数将不理会它,或者不知道。我想这是实现/用户依赖的。
简而言之,你可以用x
做任何你想做的正确事情,它应该是正确的,就像新变量一样。
因为它是move
的,所以,在g = std::move(f);
之后,f
的语义内容应该失效,g
被验证。 move
只保留语义内容的一个有效副本。
"invalidate/validate"的语义取决于类,例如,如果f
是一个字符串,则应将其设置为长度为0,如果f
是线程,则应设置为std::thread()
。但是,详细行为取决于类的移动构造函数。
当然f
仍然是可破坏的。
- 这个循环测试条件是什么意思?
- Haskell中用多态性替换条件的等效模式是什么?
- 计算文本文件中行数的最佳条件是什么
- 在条件上更新变量的最快方法是什么?
- 同时执行 if 和 else 条件的逻辑是什么
- 在发出等待条件变量的信号后,线程何时获取锁?是什么决定了它
- 这个奇怪的条件运算符语法是什么
- 编译器减少 std::copy to memcpy (memmove) 的条件是什么?
- 条件是什么意思
- 有条件地控制 for 循环方向的最佳方法是什么
- while 循环的两个条件。我的错误是什么?
- 条件语句在比较表达式时的基础是什么?
- 在 C++11 中等待多个条件变量的最佳方法是什么?
- 动态绑定的条件到底是什么
- if()语句使用条件的目的是什么?C++
- 移动构造函数的后置条件是什么
- 使用条件语句激活函数的目的是什么
- 逗号在条件语句中的优点是什么
- 在选择函数中等待fd的异常条件是什么?
- c++中的类成为容器的条件是什么?