std :: vector适用于非默认构造的类吗?

时间:2012-08-01 16:04:14

标签: c++ stl vector c++11

我在几个地方读过std :: vector要求它的模板参数是默认的可构造的。今天我只是尝试了我的一个有delete d默认构造函数的类,令我惊讶的是它似乎工作正常(使用std :: vector的默认构造函数)。这是可移植的行为,还是这是gcc的STL的实现细节,我应该假设向量要求它的模板参数是默认的可构造的吗?

4 个答案:

答案 0 :(得分:17)

在C ++ 11中有两个vector<T>成员需要默认的可构造T

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

没有别的。因此,如果您使用这些签名,则需要具有默认的可构造类型,否则您不需要。

答案 1 :(得分:13)

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

只要您尝试复制矢量或向其中插入元素,您就会遇到CopyInsertableCopyAssignableEmplaceConstructibleMoveInsertable,{{1等要求

答案 2 :(得分:6)

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

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

例如,当您在C ++ 98

中执行此类操作时
std::vector<some_type> v(42);
v.resize(64);

它实际上扩展为

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

通过默认参数机制。换句话说,默认构造的“原始”元素由调用代码提供给vector的构造函数,而不是由向量在内部创建。

C ++ 11改变了这一点,现在std::vector有方法在内部执行内部元素的默认构造。这仍然无条件地要求向量元素是可默认构造的。它只是意味着您需要使用默认构造元素来使用那些特定的std::vector方法。

答案 3 :(得分:4)

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

但是,除非您没有触及内部使用默认构造函数的方法,否则您将“安全”。但是,我不知道哪个是“安全”子集,我怀疑它没有被标准定义。示例:矢量复制可能使用resize,而{{1}}可能使用默认构造函数。