Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 堆栈的具体分配时间是什么时候_C++_C_Stack - Fatal编程技术网

C++ 堆栈的具体分配时间是什么时候

C++ 堆栈的具体分配时间是什么时候,c++,c,stack,C++,C,Stack,即使在C语言中(不仅仅是C++),也可以在代码块的开头声明变量,代码块用大括号括起来 例如: #include <stdio.h> void use_stack(int cnt) { if (cnt<=16) { int a[16]; int i; a[0]=3; a[1]=5; for (i=2;i<cnt;i++) { a[i]=a[i-1]+a[i-2];

即使在C语言中(不仅仅是C++),也可以在代码块的开头声明变量,代码块用大括号括起来

例如:

#include <stdio.h>
void use_stack(int cnt)
{
    if (cnt<=16) {
        int a[16];
        int i;
        a[0]=3;
        a[1]=5;
        for (i=2;i<cnt;i++) {
            a[i]=a[i-1]+a[i-2];
        }
        printf("a[%d] == %d\n",cnt-1,a[cnt-1]);
    }
    else {
        printf("cnt is too big\n");
    }
}
我知道这是一个丑陋的程序:-)


函数
calc
计算所有
0的
n*3+1
,自动存储的语言规则仅保证最后分配的是第一次解除分配的

编译器可以以其认为合适的任何方式实现此逻辑堆栈

如果它可以证明一个函数不是递归的,它甚至可以在程序启动时分配存储


我相信以上的内容适用于C以及C++,但我不是C专家。
当您询问编程语言的详细信息时,请将问题限制为一次一种语言。

自动存储的语言规则仅保证最后分配的是第一次释放的

编译器可以以其认为合适的任何方式实现此逻辑堆栈

如果它可以证明一个函数不是递归的,它甚至可以在程序启动时分配存储


我相信以上的内容适用于C以及C++,但我不是C专家。
当您询问编程语言的详细信息时,请将问题一次限制为一种语言。

Alf已经解释了标准规定的限制和自由(或者更确切地说,它没有规定什么)

我将提出这个问题的答案

为什么不使用大括号在代码块的开始/结束处分配/取消分配堆栈

您测试的编译器之所以选择这样做(实际上我只是猜测,我没有编写任何一个),是因为它具有更好的运行时性能和简单性(当然,也是因为它是允许的)

一次分配96字节(任意示例)所需的时间大约是两次分配48字节所需时间的一半。第三,是分配32字节的三倍

将循环视为极端情况:

for(int i = 0; i < 1000000; i++) {
    int j;
}
for(int i=0;i<1000000;i++){
int j;
}
如果在功能开始时分配了
j
,则有一个分配。如果在循环体中分配了
j
,那么将有一百万次分配。分配越少越好(越快)

注释:我假设栈在代码块的起始/结束时被分配/释放的原因是,因为在C++中,在堆栈上分配的对象的构造函数/析构函数将在代码块的起始/结束调用。 现在你知道你这样假设是错误的。正如在链接问题的精细回答中所述,分配/解除分配不必与构建/销毁一致


想象一下我会使用[100000]


这接近总堆栈空间的一个非常重要的部分。您应该像这样动态地分配大块内存。

Alf已经解释了标准规定的限制和自由(或者更确切地说,它没有规定什么)

我将提出这个问题的答案

为什么不使用大括号在代码块的开始/结束处分配/取消分配堆栈

您测试的编译器之所以选择这样做(实际上我只是猜测,我没有编写任何一个),是因为它具有更好的运行时性能和简单性(当然,也是因为它是允许的)

一次分配96字节(任意示例)所需的时间大约是两次分配48字节所需时间的一半。第三,是分配32字节的三倍

将循环视为极端情况:

for(int i = 0; i < 1000000; i++) {
    int j;
}
for(int i=0;i<1000000;i++){
int j;
}
如果在功能开始时分配了
j
,则有一个分配。如果在循环体中分配了
j
,那么将有一百万次分配。分配越少越好(越快)

注释:我假设栈在代码块的起始/结束时被分配/释放的原因是,因为在C++中,在堆栈上分配的对象的构造函数/析构函数将在代码块的起始/结束调用。 现在你知道你这样假设是错误的。正如在链接问题的精细回答中所述,分配/解除分配不必与构建/销毁一致


想象一下我会使用[100000]


这接近总堆栈空间的一个非常重要的部分。您应该像这样动态地分配大块内存。

这一操作的方式不受任何标准的约束。C和C++标准根本不提到堆栈,理论上这些语言甚至可以在没有堆栈的计算机上使用。 在有堆栈的计算机上,如何完成此操作由给定系统的指定。通常,堆栈空间在程序进入函数时保留。但是编译器可以自由地优化代码,这样只有在使用某个变量时才会保留堆栈空间

无论如何,声明变量的点与分配变量的时间没有关系。在您的示例中,
inta[16]
要么在输入函数时分配,要么就在第一个使用位置之前分配。无论是在if语句内部还是函数顶部声明
a


<>在C++中,有构造函数的概念。如果变量是具有构造函数的对象,则该构造函数将在声明变量的点处执行。这意味着在这之前必须分配变量。

这一操作的方式不受任何标准的约束。C和C++标准根本不提到堆栈,理论上这些语言甚至可以在没有堆栈的计算机上使用。 在有堆栈的计算机上,如何完成此操作由给定系统的指定。通常,堆栈空间在程序进入时保留
void
foo(int sz, int x)
{
        extern void bar(char *);
        if (x) {
                char a[sz];
                bar(a);
        } else {
                char a[10];
                bar(a);
        }
}