C 向量 emplace_back 调用复制构造函数

新手上路,请多包涵

这是一个演示课。我不希望我的类被复制,所以我删除了复制构造函数。我希望vector.emplace_back 使用这个构造函数’MyClass(Type type)‘。但是这些代码不会编译。为什么?

 class MyClass
{
public:
    typedef enum
    {
        e1,
        e2
    } Type;
private:
    Type _type;
    MyClass(const MyClass& other) = delete; // no copy
public:
    MyClass(): _type(e1) {};
    MyClass(Type type): _type(type) { /* the constructor I wanted. */ };
};

std::vector<MyClass> list;
list.emplace_back(MyClass::e1);
list.emplace_back(MyClass::e2);

原文由 wqyfavor 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 374
1 个回答

vector 需要复制构造函数,以便在需要增加存储空间时复制元素。

您可以阅读 矢量 文档

T 必须满足 CopyAssignable 和 CopyConstructible 的要求。 (直到 C++11)

对元素施加的要求取决于对容器执行的实际操作。一般要求元素类型是完整类型,满足Erasable的要求,但很多成员函数的要求更严格。 (C++11 起) (C++17 前)

对元素施加的要求取决于对容器执行的实际操作。一般要求元素类型满足 Erasable 的要求,但很多成员函数的要求更严格。如果分配器满足分配器完整性要求,则可以使用不完整的元素类型实例化此容器(但不是其成员)。

一些日志记录可以帮助您了解正在发生的事情

对于此代码

class MyClass
{
public:
    typedef enum
    {
        e1 = 1,
        e2 = 2,
        e3 = 3,
    } Type;
private:
    Type _type;
public:
    MyClass(Type type): _type(type) { std::cout << "create " << type << "\n"; };
    MyClass(const MyClass& other) { std::cout << "copy " << other._type << "\n"; }
};

int main() {
    std::vector<MyClass> list;
    list.reserve(2);
    list.emplace_back(MyClass::e1);
    list.emplace_back(MyClass::e2);
    list.emplace_back(MyClass::e3);
}

输出是

create 1
create 2
create 3
copy 1
copy 2

所以你可以 emplace_back 确实使用所需的构造函数来创建元素并在需要增加存储空间时调用复制构造函数。您可以预先调用 reserve 有足够的容量以避免调用复制构造函数。


如果由于某种原因你真的不希望它是可复制构造的,你可以使用 std::list 而不是 std::vector 因为 list 它被实现为链表,不需要移动元素。

http://coliru.stacked-crooked.com/a/16f93cfc6b2fc73c

原文由 Bryan Chen 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题