我有一个名为x的数组,其大小为6 * sizeof(float)。我知道声明:
float x[6];
将在堆栈内存中为x分配6 * sizeof(float)。但是,如果我执行以下操作:
float *x; // in class definition
x = new float[6]; // in class constructor
delete [] x; // in class destructor
我会将6 * sizeof(float)的动态内存分配给x。如果x的大小在类的生命周期中没有变化,就清洁度和速度的最佳实践而言(我隐约记得,如果不正确的话,堆栈内存操作比动态内存操作更快),我应该确定x是静态而不是动态分配的内存?提前谢谢。
答案 0 :(得分:8)
声明固定大小的数组肯定会更快。每个单独的动态分配都需要找到一个未占用的块,而且速度不是很快。
因此,如果您真的关心速度(已分析),则规则是您不需要动态分配 - 请勿使用它。如果您需要它 - 请考虑分配多少,因为重新分配也不是很快。
答案 1 :(得分:3)
使用数组成员将更干净(更简洁,更不容易出错)并且更快,因为不需要调用分配和释放功能。您还倾向于改善所分配结构的“参考局部性”。
为这样的成员使用动态分配的内存的两个主要原因是所需大小仅在运行时已知,或者所需大小很大且已知这将对可用堆栈产生重大影响目标平台上的空间。
答案 2 :(得分:2)
堆栈上的TBH数据通常位于缓存中,因此速度更快。但是,如果您动态分配一次然后定期使用它,它也将被缓存,因此速度非常快。
重要的是避免定期分配和解除分配(即每次调用函数时)。如果你只是做了常规的分配和解除分配(即只分配和释放一次),那么堆栈和堆分配的数组将完全相同的预先形成。
答案 3 :(得分:1)
是的,静态声明数组的速度会更快。
这很容易测试,只需编写一个简单的包装循环来实例化这些对象的X个数。您还可以单步执行机器代码,并查看动态分配内存所需的大量OPCODE。
答案 4 :(得分:1)
静态分配更快(无需询问内存)并且您无法忘记删除它或使用不正确的删除操作符删除它(删除而不是删除[])。
构建动态/堆数据的用法包括以下步骤:
使用静态对象/对象数组时,无需分配内存并由用户释放。这使代码更简单,更不容易出错。
总而言之,如果您在编译时知道数组上的大小并且您对内存无关(可能在运行时我将不使用数组中的条目),静态数组显然是首选的。 对于动态分配的数据,值得寻找智能指针(here)
答案 5 :(得分:1)
不要混淆以下情况:
int global_x[6]; // an array with static storage duration
struct Foo {
int *pointer_x; // a pointer member in instance data
int member_x[6]; // an array in instance data
Foo() {
pointer_x = new int[6]; // a heap-allocated array
}
~Foo() { delete[] pointer_x; }
};
int main() {
int auto_x[6]; // an array on the stack (automatic variable)
Foo auto_f; // a Foo on the stack
Foo *dyn_f = new Foo(); // a heap-allocated Foo.
}
现在:
auto_f.member_x
在堆栈中,因为auto_f
在堆栈中。(*dyn_f).member_x
在堆上,因为*dyn_f
在堆上。pointer_x
指向堆分配的数组。global_x
位于某些数据部分,操作系统或运行时每次运行程序时都会创建该部分。这可能是也可能不是与动态分配相同的堆,通常不重要。因此无论它是否在堆上,member_x
在长度始终为6的情况下比pointer_x
更好,因为:
更喜欢pointer_x
的理由:
int[262144]
的自动变量。答案 6 :(得分:0)
组合更高效,速度更快,内存开销更低,内存碎片更少。
你可以这样做:
template <int SZ = 6>
class Whatever {
...
float floats[SZ];
};
答案 7 :(得分:0)
尽可能使用堆栈分配的内存。它将使您免于解除内存释放,虚拟地址空间碎片等问题。此外,与动态内存分配相比,它更快。
答案 8 :(得分:0)
如果您静态分配arraty,则只会有一个实例。使用类的关键是你需要多个实例。根本不需要动态分配数组:
class A {
...
private:
float x[8];
};
是你想要的。
答案 9 :(得分:0)
这里有更多变数:
数组的大小与堆栈的大小:与免费存储相比,堆栈大小非常小(例如,1MB到30MB)。堆栈上的大块会导致堆栈溢出
您需要的阵列数量:大量小阵列
数组的生命周期:如果它只在函数内部需要,那么堆栈非常方便。如果您需要 函数退出后,必须在堆上分配它。
垃圾收集:如果你在堆上分配它,你需要手动清理它,或者让一些智能指针为你做好工作。
答案 10 :(得分:0)
如另一个回复中所述,无法在堆栈上分配大对象,因为您不确定堆栈大小是多少。为了便于携带,应始终在堆上分配大对象或具有可变大小的对象。
操作系统现在提供的malloc / new例程中有很多开发(例如,Solaris的libumem)。动态内存分配通常不是瓶颈。