这样使用alloca()是否有效?
Is this use of alloca() valid?
在使用标准向量保存我的国际象棋引擎的移动列表后,我意识到,由于国际象棋的平均因子为35(即从一个典型位置开始的35个合法移动),向量会调整很多,从而对移动生成器的性能产生负面影响。解决这个问题的一种方法(我今天才意识到)是为向量保留最小容量。然而,使用alloca()的可能性引起了我的注意。这可能是一个非常简单的问题,但是关于alloca()的文档非常少,关于如何使用它的示例非常非常少。
因此,来自可变大小类的分配的答案提到堆栈分配不能调整大小。然而,以下内容是否有效?
struct MoveList
{
MoveList(): capacity(10)
{
moves = (Move*) alloca(sizeof(Move) * 10);
}
void resize()
{
capacity *= 2;
moves = (Move*) alloca(sizeof(Move) * capacity );
}
void push_back();
Move* moves;
int size;
int capacity;
}
具体来说,如果第一次调用alloca()的容量为10是不够的,那么再次调用alloca()来分配更多的内存在语法上是否有效(并且正确)?这个方法会提供更好的性能(与reserve()的std vector相比),还是只会增加堆栈溢出的机会? My Move结构体需要大约28字节的内存,我怀疑引擎将递归搜索(使用alpha-beta)到最大7或8层,因此可能会从堆栈中使用大约28 * 35 * 8 ~ 8kb的最大值。我在哪里读到过,堆栈通常有1Mb的限制所以这应该不会太多,对吧?
编辑:多亏了下面的答案,我现在意识到我最初对alloca()所做的理解是错误的。但是,我仍然想知道是否有可能以以下方式使用alloca(): int main()
{
int* arr = (int) alloca(sizeof(int));
arr = alloca(sizeof(int) * 2 ));//is this 'resizing' valid?
}
函数alloca
在堆栈上分配内存,一旦调用alloca
的函数返回,内存就不再可用。这意味着只要MoveList
构造函数或resize
函数返回,内存就不再可用。你认为在MoveList
对象的生命周期内可以使用这些内存的假设是错误的。
您最好的选择是使用std::vector
并保留。
您似乎不理解非标准alloca()
表达式实际做什么。它在调用函数的堆栈帧中分配内存。在您的例子中,这意味着分配的空间(在本例中分配给moves
成员)的生命周期是构造函数的生命周期:
MoveList(): capacity(10)
{
moves = (Move*) alloca(sizeof(Move) * 10);
... moves is valid from this point
// "moves" stops being valid at this point
}
因为构造函数的其余部分是空的,所以这是而不是您想要的。(此外,alloca()
还有一个副作用,即防止调用函数内联——这是另一个意想不到的副作用。)换句话说,要回答标题中的问题,alloca()
的这种使用是无效的。
即使它在某种程度上是有效的,因为alloca()
没有对应的调整或释放分配的内存(也不能有,由于它的工作方式),它非常不适合任何需要调整区域大小的情况-这正是你试图使用它的方式。
std::vector
的大小调整能力通常已经考虑到指数增长的因素,所以添加自己的是不必要的。如果你不确定,衡量绩效,看看什么适合你。也许对于您的情况,调用std::vector<T>::reserve()
以确保向量以乐观大小开始就足够了,从而消除了重新分配的需要。或者使用std::deque
,它从不重新分配元素(代价是访问速度略慢)。
- 如果变量名称不跟在 char* 后面,const char* 是否有效?
- 钳制迭代器是否有效
- 检查由括号、方括号和大括号组成的一组方括号是否有效?
- 在函数内创建的对象的范围 - 如果在函数外部存储和访问引用,它们是否有效?
- 模板签名解析为 void(void) 被 GCC 拒绝;这是否有效C++?
- 我如何知道作为参数的size_t在函数中是否有效?
- 我的运算符重载是否有效<<(流插入)左操作数不是 ostream
- C++ 返回指向函数内定义的静态数组的指针是否有效?
- 此递归模板类型定义是否有效C++?
- 将 C 函数转换为 C++ 以检查数字是否有效
- 函数参数的名称与调用函数时使用的变量相同是否有效?
- 如何检查输入是否有效?
- 如何检查用户的输入是否有效以及我正在寻找的数字?
- 在函数中按值传递 unordered_map/unordered_set 是否有效? C++
- 如何检查isupper(cstr)是否有效?
- 将 std::transform 与 std::back_inserter 一起使用是否有效?
- 只需要知道我在c ++中打印模式的方式是否有效,或者有另一种方法可以有效地做到这一点
- 如何检查字符串格式在读取C++文本文件时是否有效?
- 在 c++ 中将对象设置为等于同一类的构造函数是否有效?
- 创建加密安全密码.并验证它是否有效