当`std :: vector`调整其内存大小时,避免任何自动变量

时间:2012-07-31 12:45:21

标签: c++ stl vector

我有std::vector<SomeType>,而SomeType是从各种模板参数中实例化的struct

最终,在我的具体情况下,它结果是一个大型结构(大约1MB)。在堆栈上分配这样的结构(即使用这种类型的自动变量)会立即导致堆栈溢出。但是由于std::vector在堆上分配内存 - 应该没有问题。

令人惊讶的是, 是一个问题。具体来说,问题在于初始化。我做了以下事情:

std::vector<SomeType> myVec;
// ...
myVec.resize(N);
for (size_t i = 0; i < N; i++)
{
    SomeType& x = myVec[i];
    // initialize it
}

我在myVec.resize()中遇到了堆栈溢出异常。使用调试器在resize()内部步进显示,如果resize()导致vector增长 - 除了分配内存外,它还会按“默认值”初始化新元素。

“默认值”是通过使用默认(即空)构造函数创建给定类型的自动变量,并为其指定新元素来获得的。

我想知道是否有办法克服这个问题。我的意思是,告诉std::vector不要初始化新元素。但我想实现这个而不会产生不必要的代码

我可以考虑使用vector(智能/共享/范围/唯一)指针来键入。或者使用push_back,而每个新元素都在堆上分配。但所有这一切都不可避免地涉及额外的代这是没有道理的。

有没有办法达到我的需要?鉴于:

  • 仍在使用std::vector<SomeType>
  • 没有冗余堆分配

提前致谢

3 个答案:

答案 0 :(得分:4)

在C ++ 03中,这是不可能的:

  • 向量不能包含未初始化的元素
  • 向量知道如何通过复制来初始化元素

因此您需要复制元素。它不适合堆栈(排除默认参数),你不想明确地把它放在别处,所以你运气不好。

在C ++ 11中,有一种初始化容器中元素的新方法,例如size_t构造函数不再需要额外的默认参数。相反,它会初始化每个元素,这可能就是你想要的。

所以在C ++ 11中,答案是std::vector<SomeType> myVec(N);。也许您可以检查您的编译器是否具有可用于编译代码的C ++ 11模式。当然,迁移到C ++ 11并不是完全无足轻重的。

答案 1 :(得分:2)

使用reserve然后使用push_back。

答案 2 :(得分:2)

最佳解决方案是更改SomeType以使其更小。但是可以在不使用堆栈或堆的情况下调整向量的大小。只需使用静态局部变量:

static SomeType intialValue;
myVec.resize(N, initialValue);

请注意,此类功能不可重复使用。