我目前正在填充像这样的元素的矢量数组:
std::vector<T*> elemArray;
for (size_t i = 0; i < elemArray.size(); ++i)
{
elemArray = new T();
}
代码显然已经简化了。在询问了另一个question(与此问题无关但与程序相关)后,我意识到我需要一个具有new'd
个对象的数组(不能在堆栈上,会溢出,元素太多)但是是连续的。也就是说,如果我要接收一个没有数组索引的元素,我应该能够通过执行returnedElement - elemArray[0]
来获取数组索引,以获取数组中元素的索引。
我希望我已经解释了这个问题,如果没有,请告诉我哪些部分,我会尝试澄清。
编辑:我不确定为什么最高投票的答案没有被调查。我已经尝试了很多次。如果我尝试分配一个超过100,000(大约)元素的向量,它总是给我一个内存错误。其次,我需要指针,从我的例子可以清楚地看出。突然改变它不是指针将需要大量的代码重写(虽然我愿意这样做,但它仍然没有解决分配像这样的几百万元素的向量不起作用的问题。
答案 0 :(得分:4)
std::vector<>
将其元素存储在堆分配的数组中,它不会将元素存储在堆栈中。所以即使你这么做,你也不会有任何堆栈溢出:
std::vector<T> elemArray;
for (size_t i = 0; i < elemCount; ++i) {
elemArray.push_back(T(i));
}
&elemArray[0]
将是指向T
个对象的(连续)数组的指针。
答案 1 :(得分:3)
如果你需要连续的元素而不是指针,你可以这样做:
std::vector<T> elemArray(numberOfElements);
元素本身不在堆栈中,vector
管理内存的动态分配,并且在您的示例中,元素将进行值初始化。 (严格地说,从值初始化的临时值进行复制初始化,但对于有效存储在向量中的对象,这应该是相同的。)
我认为您的索引计算应该是:&returnedElement - &elemArray[0]
,这将适用于vector
。前提是returnedElement
实际存储在elemArray
。
答案 2 :(得分:1)
你的原始循环应该是这样的:(虽然它不会在连续的内存中创建对象)。
for (size_t i = 0; i < someSize ; ++i)
{
elemArray.push_back(new T());
}
然后你应该知道两个基本的事情:
elemArray.size()
返回当前包含的元素数elemArray
。这意味着,如果您在for
循环的条件下使用它,那么您的for
循环将变为无限循环,因为您正在向其添加元素,因此向量的大小将继续增加。 elemArray
是T*
的向量,因此您只能存储T*
,并且要填充它,您必须使用push_back
函数。答案 3 :(得分:1)
考虑到您的旧代码导致堆栈溢出,我认为它可能看起来像这样:
Item items[2000000]; // stack overflow
如果是这种情况,那么您可以使用以下语法:
std::vector<Item> items(2000000);
这将在堆上连续分配(和构造)项目。
答案 4 :(得分:1)
虽然我也有相同的要求,但出于不同的原因,主要是因为缓存热...(对于少量对象)
int maxelements = 100000;
T *obj = new T [100000];
vector<T *> vectorofptr;
for (int i = 0; i < maxelements; i++)
{
vectorofptr.push_back(&obj[i]);
}
或
int sz = sizeof(T);
int maxelements = 100000;
void *base = calloc(maxelements, sz); //need to save base for free()
vector<T *> vectorofptr;
int offset = 0;
for (int i = 0; i < maxelements; i++)
{
vectorofptr.push_back((T *) base + offset);
offset += sz;
}
答案 5 :(得分:0)
分配大量内存并使用placement new
构建其中的向量元素:
elemArray[i] = new (GetNextContinuousAddress()) T();
(假设您确实需要指向数组中的新生对象的指针,并且知道不建议这样做的原因..)
答案 6 :(得分:0)
我知道这是一个老帖子,但对于任何可能需要它的人来说,它可能是有用的英特尔。只有当你想到一些重要的警告时,在序列容器中存储指针才是完美的:
您存储的指针所指向的对象将不会在内存中连续对齐,因为它们是在程序的其他位置(动态或非动态)分配的,您最终会得到一个指向可能分散的数据的连续指针数组跨记忆。
由于STL容器使用值复制而不是引用副本,因此容器不会获取已分配数据的所有权,因此只会删除销毁时的指针对象,而不会删除它们指向的对象。当没有动态分配这些对象时,这很好,否则你需要在尖头对象的其他地方提供一个释放机制,比如简单地遍历你的指针并单独删除它们或使用共享指针,这些指针将在需要时为你完成工作; - )
要记住的最后但非常重要的事情是,如果您的容器要在动态环境中使用,并且可能在随机位置插入和删除,您需要确保使用稳定的容器,以便您的迭代器/指向存储元素的指针在这些操作之后仍然有效,否则你最终会产生不良副作用......这就是std :: vector的情况,它会在插入新元素时释放并重新分配额外空间,然后执行移位元素的副本(除非你在最后插入),从而使元素指针/迭代器无效(虽然有些实现提供稳定性,比如boost :: stable_vector,但这里的惩罚是你丢失了容器的连续属性,编程时不存在魔法,生活是不公平的吗?; - ))
此致