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

标签 c++ oop constructor stl allocator

我有一个如下所示的类:

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

    PasswordCategory() = delete;
    ...
}

这会导致与分配器相关的编译器错误:

error C2280: 'PasswordCategory::PasswordCategory(void)' : attempting to reference a deleted function
File: xmemory0:577

IDE 是 VS 2013 社区。

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

std::vector<PasswordCategory> m_categories;

我只使用 emplace_back(string) 向其中插入元素,但是,PasswordCategory 的默认分配器似乎尝试使用 PasswordCategory 的默认构造函数,但由于它已被删除,因此会引发错误。

如果我提供默认构造函数,一切都会正常工作,但我想知道如何在没有默认构造函数的情况下缓解此问题(如果有的话)?

我想到了以下解决方案:

  1. 为我的类提供一个自定义分配器来构造我的类。但是,这并不能解决我希望字符串参数是非可选的问题。
  2. 提供默认构造函数,该构造函数仅使用一些参数调用我的其他构造函数。这也没有解决这个参数是非可选的并且不应该被默认的问题。
  3. 使用引用或指针 vector 而不是值 vector 。这似乎是最合理的解决方案,但是它需要手动管理内存,除非我们使用 unique_ptr 或类似的东西。

我想知道是否可以以某种方式禁止我的类的无参数构造,同时仍然能够按值在标准容器中使用它?

感谢任何答案和见解,提前致谢。

附注这是我为了更好地理解 C++ 所做的一个小项目,我试图避免大多数常见的陷阱并使一切尽可能可靠,以便当我要从事更大的项目时,我会更容易避免这些常见的陷阱。我尝试以不同的方式提出问题,但没有找到问题的答案,所以我问自己的问题。

最佳答案

std::vector 本身并不要求 TDefaultConstructible 类型:

C++ 11 之前:

T must meet the requirements of CopyAssignable and CopyConstructible.

自 C++ 11 起:

The requirements that are imposed on the elements depend on the actual operations performed on the container. Generally, it is required that element type is a complete type and meets the requirements of Erasable, but many member functions impose stricter requirements.

参见this page了解详情。

但是,您可能会对容器执行涉及创建隐式实例的操作,这就是您收到此错误的原因。如果您可以跟踪它们并消除它们,那么一切都应该正常工作,因为如果不使用默认构造函数,则根本不需要它。

考虑您的建议:

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

这不会有帮助 - std::allocator 不负责默认构造元素,因为它根本没有定义此类功能。请参阅std::allocator::construct .

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

C++ 11 之前

void construct( pointer p, const_reference val );

自 C++ 11 起

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

2. 提供默认构造函数,该构造函数仅使用一些参数调用我的其他构造函数。

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

3.使用引用或指针 vector 而不是值 vector 。

这似乎是最合理的解决方案,但是它引入了手动管理内存的需要,除非我们使用 unique_ptr 或类似的东西。 不太有效 - 您无法创建引用容器。最接近的解决方案是容器,其中包含 std::reference_wrapper s。原始/智能指针的容器也是一种选择,但这就是问题所在,事情开始变得困惑。

此外,在您的原始代码中,无需声明已删除的默认构造函数 - 如果您声明任何构造函数,则意味着没有默认构造函数(除非您定义它)​​并且编译器获胜不生成任何内容。

关于c++ - 删除默认构造函数会导致 STL 容器中的默认分配器出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29346518/

相关文章:

c++ - 从 vector 私有(private)继承,公开相等运算符

java - 具有外部类和内部类的数组

c++ - 是否可以从图像计算速度?

java - 在状态设计模式中使用组合和实现

oop - "A method should do one thing, once and only once"- 这是什么意思?

c++ - 在 C++ 中,构造函数和析构函数可以是内联函数吗?

java - 如何从构造函数返回错误消息(字符串)?

python - 更改子类中的默认构造函数参数值(从父类继承)

c++ - 如何使用递归反转打印堆栈?

c++ - std::vector<std::vector<Vertex>> 顶点矩阵;在这方面没有申明