我有一个如下所示的类:
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 社区。p>
我假设发生这种情况是因为我在其他地方使用这些类别的 vector 。
std::vector<PasswordCategory> m_categories;
我只使用 emplace_back(string) 向其中插入元素,但是,PasswordCategory 的默认分配器似乎尝试使用 PasswordCategory 的默认构造函数,但由于它已被删除,因此会引发错误。
如果我提供默认构造函数,一切都会正常工作,但我想知道如何在没有默认构造函数的情况下缓解此问题(如果有的话)?
我想到了以下解决方案:
- 为我的类提供一个自定义分配器来构造我的类。但是,这并不能解决我希望字符串参数是非可选的问题。
- 提供默认构造函数,该构造函数仅使用一些参数调用我的其他构造函数。这也没有解决这个参数是非可选的并且不应该被默认的问题。
- 使用引用或指针 vector 而不是值 vector 。这似乎是最合理的解决方案,但是它需要手动管理内存,除非我们使用 unique_ptr 或类似的东西。
我想知道是否可以以某种方式禁止我的类的无参数构造,同时仍然能够按值在标准容器中使用它?
感谢任何答案和见解,提前致谢。
附注这是我为了更好地理解 C++ 所做的一个小项目,我试图避免大多数常见的陷阱并使一切尽可能可靠,以便当我要从事更大的项目时,我会更容易避免这些常见的陷阱。我尝试以不同的方式提出问题,但没有找到问题的答案,所以我问自己的问题。
最佳答案
std::vector
本身并不要求 T
是 DefaultConstructible
类型:
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/