gpt4 book ai didi

c++ - map move 插入是否保证元素被 move 或不被 move ?

转载 作者:可可西里 更新时间:2023-11-01 15:06:43 26 4
gpt4 key购买 nike

C++ 中的标准“映射”容器允许您插入右值:

T x;

std::map<int, T> m;

// m[1]; // populate "1"

auto it = m.insert(std::make_pair(1, std::move(x)));

问题是当元素已经存在时会发生什么,即 it->second == false。元素 x 是否已被“移出”?例如,如果它是一个唯一指针,x 是否已被重置为 null?

显然,上述情况的答案是"is",因为移出已经在创建对时发生了。但是假设现在我想更新现有值,但仍然保留该值是否已经存在的信息(所以我不能只说 m[1] = std::move(x);)。在那种情况下是否可以“不离开”对象?

我在 GCC 中发现以下工作 [更新:在 GCC 4.6 中工作,在 GCC 4.8 中工作]:

auto it = m.insert(std::pair<const int, T &&>(1, std::move(x)));

但这能保证不动吗?

最佳答案

虽然std::move实际上并没有执行任何 move ,std::make_pair 也没有, std::make_pair将其参数转发给 std::pair构造函数,它从这些参数初始化它的两个值成员。

因此, move 在那个点执行,在 std::map 之前有机会做任何事情。所以,是的,您最终会无缘无故地“失败”。

您应该能够利用 emplace (为了跳过对结构)。来自表 102:

Effects: Inserts a T object t constructed with std::forward<Args>(args)... if and only if there is no element in the container with key equivalent to the key of t.

显然,此时库仍在“转发”,因此它是 move 前的,在您的情况下,不会发生任何位置,因此整个表达式应该是一个有效的空操作。

但是libstdc++ 来自GCC 4.8.0 appears to have a bug在这方面: emplace 调用 _M_emplace_unique on the internal tree , 它将参数转发给 _M_create_node , 它将参数转发给 allocator_traits<_Node_allocator>::construct , 它将参数转发给 _S_construct , 它将参数转发给 __a.construct对于默认分配器,它是 std::allocator<std::pair<const _Key, _Tp> >::construct ,这是你试图避免的对构造函数......所有在碰撞检查之前 _M_emplace_unique .

可以说标准在这方面模棱两可,但我认为这是违反意图的。然后,clang v3.4 with libc++ exhibits this behaviour too ,Visual Studio 2012 也是如此。因此,如果我的标准解释是正确的,那么这在所有三个主流工具链上都会失败。

我猜他们都决定将“当且仅当”应用于插入,而不是插入构造。

我已经在 std-discussion 上发布了一个问题旨在激发对表 102 中段落的改进,以一劳永逸地权威地回答这个问题。

关于c++ - map move 插入是否保证元素被 move 或不被 move ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20328242/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com