繁体   English   中英

为什么std :: insert需要CopyConstructibility?

[英]Why does std::insert require CopyConstructibility?

为什么此代码不起作用? 对于std :: map的insert方法,文档中没有关于CopyConstructibility的内容: http ://en.cppreference.com/w/cpp/container/map/insert

我可以构造std :: pair,第二个元素是我的non_copyable类,但是即使insert方法的第一个重载采用const value_type&,也无法将其插入到map中,所以应该可以正常工作。

有人可以帮助我了解为什么std :: map需要此CopyConstructibility吗?

#include <utility>
#include <map>

struct non_copyable {
    non_copyable(){}

private:
    non_copyable(const non_copyable&);
};

int main() {
    std::pair<int, non_copyable> p; // this works!

    std::map<int, non_copyable> m;
    m.insert(std::pair<int, non_copyable>()); // this does NOT work
}

示例: https//wandbox.org/permlink/r3H6CqehfqnHPXDL

...即使insert方法的第一个重载采用const value_type& ,所以也可以正常工作。

不,实际上,在这种情况下,正确的过载解决方案候选对象是:

m.insert(std::pair<int, non_copyable>());

这是重载的成员函数:

template< class P >
std::pair<iterator,bool> insert( P&& value );

现在, 此页面描述了为什么它不起作用:

...仅在std::is_constructible<value_type, P&&>::value == true参与重载解析。

您的non_copyable不可构造:

using M = std::map<int, non_copyable>;
using P = std::pair<int, non_copyable>;
std::is_constructible<M::value_type, P&&>::value; // false

因为没有可用的构造函数,包括由编译器生成的默认隐式move构造函数。

non_copyable甚至禁用其默认的隐式move构造函数的原因是,由于具有用户定义的副本构造函数,如文档所述

如果没有为类类型(struct,class或union)提供用户定义的move构造函数,则以下所有条件均成立:

没有用户声明的副本构造函数

没有用户声明的副本分配运算符

没有用户声明的移动分配运算符

没有用户声明的析构函数

现在给non_copyable一个move构造函数成为您的责任:

struct non_copyable {
    non_copyable(){}
    non_copyable(non_copyable &&) = default;

private:
    non_copyable(const non_copyable&);
};

您可能会感兴趣,为什么您根本不需要制作任何副本,因此即使您可以在地图内部直接构造(成对)对,也要提供可构造副本的类型。

这是因为要提供所需的性能,通常将std :: map的内部表示形式实现为平衡的二进制搜索树(最终作为具有相似性能特征的另一个数据结构),这需要存储元素的某些特定顺序。 因此,在添加或删除某些元素之后,该顺序可能会中断,并且为了保持其正确性,有时需要存储的元素进行内部移动。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM