C++ 删除默认构造函数会导致STL容器中的默认分配器出现问题

C++ 删除默认构造函数会导致STL容器中的默认分配器出现问题,c++,oop,constructor,stl,allocator,C++,Oop,Constructor,Stl,Allocator,我有一个类似这样的类: class PasswordCategory { public: PasswordCategory(const std::string&); ~PasswordCategory(); PasswordCategory() = delete; ... } 这会导致与分配器相关的编译器错误: 错误C2280:'PasswordCategory::PasswordCategory(void)':正在尝试 引用已删除函数的步骤文件:xm

我有一个类似这样的类:

class PasswordCategory
{
public:
    PasswordCategory(const std::string&);
    ~PasswordCategory();

    PasswordCategory() = delete;
    ...
}
这会导致与分配器相关的编译器错误:

错误C2280:'PasswordCategory::PasswordCategory(void)':正在尝试 引用已删除函数的步骤
文件:xmemory0:577

IDE是VS2013社区

我假设发生这种情况是因为我在其他地方使用这些类别的向量

std::vector<PasswordCategory> m_categories;
std::向量m_类;
我只使用emplace_back(string)将元素插入其中,但是,似乎PasswordCategory的默认分配器正在尝试使用PasswordCategory的默认构造函数,但由于该构造函数已被删除,因此会抛出一个错误

如果我提供默认构造函数,一切都很好,但我想知道如果没有默认构造函数,我如何缓解这个问题

我想到了以下解决方案:

  • 为构造类的类提供自定义分配器。但是,这并不能解决我希望字符串参数是非可选的问题
  • 提供默认构造函数,该构造函数仅使用一些参数调用我的另一个构造函数。这也不能解决这个参数是非可选的,不应该被默认的问题
  • 使用引用或指针的向量而不是值的向量。这似乎是最合理的解决方案,但是它引入了手动管理内存的需求,除非我们使用unique_ptr或类似的东西
  • 我想知道我是否可以以某种方式禁止类的arg-less构造,同时仍然能够按值在标准容器中使用它

    任何答案和见解都将不胜感激,提前感谢


    这是我的一个小项目,为了更好地理解C++,在这里我试图避免大多数常见的陷阱,并使所有的事情尽可能可靠,这样当我要做一个更大的项目时,我就更容易避免这些常见的陷阱。我试着用不同的方式表达这个问题,但没有找到我问题的答案,所以我只问我自己的问题。

    原则上,你不能:标准容器要求包含的对象是默认可构造的。(见迈克·西摩的评论)

    原则上,您应该能够,除非您在内部使用需要默认构造的操作

    这就是说,您可以简单地创建一个空构造函数(默认成员为sane/使用一些参数调用另一个构造函数)。如果正确编写客户机代码,则不会遇到使用默认值初始化的对象


    需要默认构造对象的操作通常是调整大小,以及其他一些需要创建内部对象的操作(即,除非您想保留一个元素并在不显式初始化它的情况下使用它,否则您不应该有问题).

    std::vector
    本身不要求
    t
    DefaultConstructible
    类型:

    <强>直到C++ 11:

    T必须满足可复制分配和可复制构造的要求

    <强> C++ 11:< /强> < /P> 对构件施加的要求取决于对容器执行的实际操作。通常,要求元素类型为完整类型并满足可擦除的要求,但许多成员函数的要求更为严格

    有关详细信息,请参阅

    然而,您可以在容器上执行操作,这涉及到创建隐式实例,这就是为什么会出现此错误。如果您可以跟踪并消除它们,那么一切都应该正常工作,因为如果不使用默认构造函数,就不需要它

    考虑到你的建议:

    1。为构建类的类提供自定义分配器

    这不会有任何帮助-
    std::allocator
    不负责默认的构造元素,因为它只是不定义这样的功能。看

    编辑 这里有点小错误,我没有注意到C++ 11中的小变化:

    <强>直到C++ 11

    void construct( pointer p, const_reference val );
    
    template< class U, class... Args >
    void construct( U* p, Args&&... args );
    

    <强> C++ 11 < /强>

    void construct( pointer p, const_reference val );
    
    template< class U, class... Args >
    void construct( U* p, Args&&... args );
    
    template
    无效构造(U*p、参数和参数);
    
    2。提供默认构造函数,该构造函数只调用我的另一个构造函数,并带有一些参数

    这也不能解决这个参数是非可选的,不应该被默认的问题。 这也不是完全可移植的。有些编译器(如VC11)不支持委托构造函数

    3.使用引用向量或指针而不是值向量

    这似乎是最合理的解决方案,但是它引入了手动管理内存的需求,除非我们使用unique_ptr或类似的东西。 不完全有效-无法创建引用的容器。最接近的解决方案是容器,它容纳s。原始/智能指针的容器也是一个选项,但这就是问题所在,事情开始变得一团糟


    另外,在您的原始代码中,不需要声明已删除的默认构造函数-如果您声明any构造函数,这意味着没有默认构造函数(除非您定义它),编译器不会生成任何构造函数。

    您能确切地告诉我们您是如何处理导致错误的向量吗?如果实现符合C++11/14,只要您不做任何特别需要默认构造函数的事情(例如,使用单个参数调用
    resize
    )。定义一个空向量,并使用适当的构造函数参数调用
    emplace\u back
    ,应该可以。啊,这很奇怪。读了你的评论后,我终于找到了罪犯。我正在使用0参数初始化向量:
    PasswordManage