当“std::vector”调整内存大小时,避免使用任何自动变量
Avoiding any automatic variables when `std::vector` resizes its memory
我有一个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
(smart/shared/scoped/unique)指针来类型。或者使用push_back
,而每个新元素都在堆上分配。但所有这些不可避免的事情都涉及到额外的代码。这是不合理的。
有没有办法达到我的需要?鉴于:
- 仍在使用
std::vector<SomeType>
- 无冗余堆分配
提前感谢
在C++03中,这是不可能的:
- 矢量不能包含未初始化的元素
- 矢量只有知道如何通过复制初始化元素
因此,您需要从中复制一个元素。它不适合堆栈(排除了默认参数),而且你不想明确地把它放在其他地方,所以你运气不好。
在C++11中,有新的初始化容器中元素的方法,例如size_t
构造函数不再使用额外的默认参数。相反,它值初始化每个元素,这可能是您想要的。
所以在C++11中,答案是std::vector<SomeType> myVec(N);
。也许您可以检查编译器是否有可用于编译代码的C++11模式。当然,迁移到C++11并不是一件小事。
使用reserve,然后使用push_back。
最好的解决方案是更改SomeType
,使其更小。但在不使用堆栈或堆的情况下调整向量大小是可能的。只需使用一个静态局部变量:
static SomeType intialValue;
myVec.resize(N, initialValue);
请注意,这样的功能是不可重新进入的。
- 共享指针和具有自定义删除程序的唯一指针之间的语法差异背后的任何原因
- C++类型特征,以查看是否可以<uint32_t>对类型"K"的任何变量调用"static_cast(k)"
- 为什么静态数组成员变量在调用对象的实例后不显示任何内容?
- 自定义宽度变量
- 为自定义打印调试实现传递任何类型的变量
- 为什么当我没有变量或其他任何命名的东西时"no match for 'operator==' "错误?
- 是否有任何统一的方法可以在 c++ 中创建自定义比较器?
- C++ priority_queue与自定义比较器并删除任何项目
- 为什么我的变量在我尚未将其设置为任何值时返回一个值?
- "... already defined in *.obj"但我没有在同一范围内两次定义任何变量
- 带有自定义类的共享指针语法背后的任何原因,如下所示
- 如何对 int 变量应用验证,使其仅接受整数数据,并且在任何其他数据的情况下不会出错?
- 我们是否可以保证任何原子写入都会立即将原子变量的新值存储在主存储器中?
- 如果类没有任何成员变量,则通过临时对象调用类的成员函数的开销是多少?
- 我可以在没有任何实例变量的情况下使用 decltype 吗?
- 当“std::vector”调整内存大小时,避免使用任何自动变量
- 这是在没有任何临时变量的情况下反转字符串的好方法吗?
- 无法将字符串转换为 int 作为回报。在 int 返回函数 getsocial() 中没有声明任何字符串变量
- 在初始化任何自动变量之前使用它
- 是指向任何类型变量的指针