Hello,请问标准是否有保证 std::map 的 move constructor 后 other 为空?

2019-07-08 11:31:14 +08:00
 wutiantong
map( map&& other )
2311 次点击
所在节点    C
12 条回复
blinue
2019-07-08 12:56:47 +08:00
没有。移动构造后 other 处于某个合法但不确定的状态,不保证为空,取决于具体实现
wutiantong
2019-07-08 13:22:11 +08:00
@blinue 如果是 vector,other 是会为空的,cppreference 上有提到这点; https://stackoverflow.com/a/17735913/6947776 这里有更详细的解释:
This operation must have constant complexity ...So for the move constructor, yes, the moved-from vector will always be empty. This is not directly specified, but falls out of the complexity requirement, and the fact that there is no other way to implement it.

而 map 的相关信息不多,cppreference 也没提到 other 是否为空的事情,但有复杂度的条款:
Constant. If alloc is given and alloc != other.get_allocator(), then linear.

所以我很好奇这里会不会也和 vector 有类似的情况。
bumz
2019-07-08 14:43:57 +08:00
并不是,我不一定要 move 之后为空
因为标准没说 move 之后的容器应该啥样,只说你不该用它

我直接把它加一个 flag 叫 invalid,析构的时候跳过
其他方法并不检查 invalid,这也符合标准

所以任何标准没说的东西,为了可移植性,原则上不应当依赖。
bumz
2019-07-08 14:47:41 +08:00
@bumz 更正,这个 flag 不应该叫 invalid
叫 moved 就行
然后规定 moved 对象你不能用,只能等他析构

这也符合标准,因为标准没规定 move 之后需要处在什么状态

“ valid but unspecifiedl ”
bumz
2019-07-08 14:55:50 +08:00
@bumz 准确的说任何需要 precondition 的操作,都不能在 moved 对象上用,但是你完全可以给他一个新的值
wutiantong
2019-07-08 15:21:19 +08:00
@bumz 我问的是 special case,而不是 general case,你应该看看我在前面放的一些描述和引用。
lrxiao
2019-07-08 22:52:44 +08:00
这个 SO 回答有问题... constant time 没有任何隐含 moved 就会 empty 的关系...如果标准使得必须 empty,那也不是有意为之
wutiantong
2019-07-09 10:52:33 +08:00
@lrxiao 我没懂你后半句。然后我还是觉得这个 SO 回答得蛮靠谱的,你所说的“ constant time 没有任何隐含 moved 就会 empty 的关系.” 能否进一步解释一下?或者给个例子论证一下呢?
hxy1ng
2019-07-09 11:42:48 +08:00
这个答案有问题吧,他可能想当然的认为

this->data = other.data;
other.data = nullptr;

但是没有人规定要把 other.data 设成 nullptr。如果你担心析构时的问题,一般确实是这样写的:

if (this->data) delete[] this->data;

但是我完全可以自己加一个私有变量 bool

if (!moved) delete[] this->data;
wutiantong
2019-07-09 13:53:22 +08:00
不想再继续解释了,希望有真正了解 standard 的同学来回答一下。
bumz
2019-07-10 15:05:32 +08:00
@wutiantong 那个回答是错的

同样类比这个逻辑到 map 也是错的

了解 standard 就是知道标准没规定什么,所以为了可移植不应该依赖什么

过度解读不叫了解标准

你要是想要把你目前用的实现当标准,不要可移植性,就去看它的源代码
wutiantong
2019-07-10 15:23:26 +08:00
@bumz 即便那个回答里相关的因果关系是错的,但我所关心的其实是“ vector move constructor make other empty ”这个结论,你可以看一下 https://en.cppreference.com/w/cpp/container/vector/vector 其中明确提到:

After the move, other is guaranteed to be empty().

当然我也知道 cppreference 并不代表 C++标准,但它的准确度还是很高的。那么:

1 )如果你觉得这一条是符合标准的;那能否顺手给我指引一下出处,如果能进一步指出与 map 情况相关的出处就更感谢了。
2 )如果你有充分的理由觉得这一条是杜撰的,不存在的;那你也许可以做点儿好事,给 cppreference 提个 issue,给那个 SO 回答加一条 comment。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/580943

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX