V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wutiantong
V2EX  ›  C

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

  •  
  •   wutiantong · 2019-07-08 11:31:14 +08:00 · 2296 次点击
    这是一个创建于 1725 天前的主题,其中的信息可能已经有所发展或是发生改变。
    map( map&& other )
    12 条回复    2019-07-10 15:23:26 +08:00
    blinue
        1
    blinue  
       2019-07-08 12:56:47 +08:00 via Android
    没有。移动构造后 other 处于某个合法但不确定的状态,不保证为空,取决于具体实现
    wutiantong
        2
    wutiantong  
    OP
       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
        3
    bumz  
       2019-07-08 14:43:57 +08:00 via iPhone
    并不是,我不一定要 move 之后为空
    因为标准没说 move 之后的容器应该啥样,只说你不该用它

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

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

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

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

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

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

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

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

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

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

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

    过度解读不叫了解标准

    你要是想要把你目前用的实现当标准,不要可移植性,就去看它的源代码
    wutiantong
        12
    wutiantong  
    OP
       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。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1237 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 17:58 · PVG 01:58 · LAX 10:58 · JFK 13:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.