11

我在几个地方读到 std::vector 要求它的模板参数是默认可构造的。今天我刚刚用我的一个具有deleted 默认构造函数的类进行了尝试,令我惊讶的是,它似乎工作得很好(使用 std::vector 的默认构造函数)。这是可移植的行为,还是 gcc 的 STL 的实现细节,我应该假设 vector 要求它的模板参数是默认可构造的?

4

4 回答 4

20

There are two vector<T> members that require a default constructible T in C++11:

explicit vector(size_type n);
void resize(size_type sz);

Nothing else does. So if you use these signatures, you need to have a default constructible type, else you do not.

于 2012-08-01T17:10:07.887 回答
15

C++03 中的要求是存储在容器中的类型是CopyConstructibleAssignable(参见 §23.1 容器要求)。但是,在 C++11 中,这些要求被放宽了,并且倾向于适用于在容器上执行的操作。因此,一个简单的默认构造没有任何要求(参见 teble 96, §23.1 in C++11 标准)。

只要您尝试复制矢量或向其中插入元素,您将满足CopyInsertable, CopyAssignable, EmplaceConstructible,MoveInsertableMoveAssignable要求

于 2012-08-01T16:13:59.157 回答
7

std::vector不无条件地要求其元素类型是默认可构造的。

(C++98, C++03)的原始规范std::vector甚至从未尝试在内部默认构造其元素。所有新元素总是从“从外部”(由调用代码)作为参数提供的对象复制构造。这意味着每次您需要向量中的默认构造元素时,您代码(调用者)必须默认构造它并将其std::vector作为要复制的“原始”元素提供。

例如,当你在 C++98 中做这样的事情时

std::vector<some_type> v(42);
v.resize(64);

it actually expands into

std::vector<some_type> v(42, some_type(), allocator_type());
v.resize(64, some_type());

through the default argument mechanism. In other words, the default-constructed "original" element is supplied to vector's constructor by the calling code, not created internally by the vector.

C++11 changed that and now std::vector has methods that perform default construction of its elements internally. This still does not unconditionally require vector elements to be default-constructible. It just means that you need default-constructible elements to use those specific std::vector's methods.

于 2012-08-01T16:56:36.990 回答
4

嗯,模板在某种意义上是弱类型的。也就是说,在您的代码调用使用它的方法之前,可能不会在内部检测到缺少的默认构造函数——这将产生编译时错误。

但是,除非您不接触在内部使用默认构造函数的方法,否则您是“安全的”。但是,我不知道哪个是“安全”子集,并且我怀疑它没有被标准定义。示例:向量复制可能使用resize,而后者又可能使用默认构造函数。

于 2012-08-01T16:10:35.237 回答