gpt4 book ai didi

c++ - Visual Studio 2017 是否需要显式移动构造函数声明?

转载 作者:可可西里 更新时间:2023-11-01 18:39:49 24 4
gpt4 key购买 nike

以下代码可以使用 Visual Studio 2015 成功编译,但使用 Visual Studio 2017 失败。Visual Studio 2017 报告:

error C2280: “std::pair::pair(const std::pair &)”: attempting to reference a deleted function

代码

#include <unordered_map>
#include <memory>

struct Node
{
std::unordered_map<int, std::unique_ptr<int>> map_;
// Uncommenting the following two lines will pass Visual Studio 2017 compilation
//Node(Node&& o) = default;
//Node() = default;
};

int main()
{
std::vector<Node> vec;
Node node;
vec.push_back(std::move(node));
return 0;
}

看起来 Visual Studio 2017 显式需要移动构造函数声明。这是什么原因?

最佳答案

最小的例子:

#include <memory>
#include <unordered_map>
#include <vector>

int main() {
std::vector<std::unordered_map<int, std::unique_ptr<int>>> vec;
vec.reserve(1);
}

GodBolt 现场演示:https://godbolt.org/z/VApPkH .


另一个例子:

std::unordered_map<int, std::unique_ptr<int>> m;
auto m2 = std::move(m); // ok
auto m3 = std::move_if_noexcept(m); // error C2280

更新

我相信编译错误是合法的。 Vector 的重新分配函数可以使用 std::move_if_noexcept 传输元素(的内容) ,因此更喜欢复制构造函数而不是抛出移动构造函数。

在 libstdc++ (GCC)/libc++ (clang) 中,移动 std::unordered_map 的构造函数是(表面上)noexcept .因此,移动 Node 的构造函数是noexcept同样,它的复制构造函数根本不涉及。

另一方面,MSVC 2017 的实现似乎没有指定 std::unordered_map 的移动构造函数作为noexcept .因此,移动 Node 的构造函数不是 noexcept同样, vector 的重新分配功能通过std::move_if_noexcept尝试调用 Node 的复制构造函数.

Node 的复制构造函数被隐式定义为调用 std::unordered_map 的复制构造函数.但是,后者可能不会在此处调用,因为映射的值类型(在本例中为 std::pair<const int, std::unique_ptr<int>>)不可复制。

最后,如果您自定义 Node 的移动构造函数,其隐式声明的复制构造函数被定义为已删除。 并且,IIRC,删除了隐式声明的复制构造函数不参与重载决议。但是,std::move_if_noexcept 不考虑删除的复制构造函数, 因此它将使用 Node. 的 throw 构造函数

关于c++ - Visual Studio 2017 是否需要显式移动构造函数声明?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54421110/

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