为什么必须声明必须由函数返回的数组作为静态?

时间:2014-09-01 10:58:00

标签: c++ arrays pointers

我的问题类似于一些相关问题,但这些问题的答案并不能解决我的主要困惑。我试着以最简单的形式提出这个问题。

我想返回一个在函数体内定义的数组。由于C ++不允许按值返回数组,因此我声明函数返回指针。

为什么需要在函数体内声明此数组static才能在主程序中访问?我知道局部变量在退出函数体时被破坏了,但是函数仍然返回一个指向这个数组的指针,不是吗?

float *doubleEachElement(float *arr)
{
    static float result[3]; // static keyword is necessary
    for (int i = 0; i != 3; i++) result[i] = 2 * arr[i];
    return result;
}

int main()
{
    float a[3] = {1.0, 2.0, 3.5};
    float *a2;
    a2 = doubleEachElement(a);
    for (int i = 0; i!=3; i++) cout << a[i] << " * 2 = " << *(a2+i) << endl;
    // only prints out correctly if the value is declared static inside the function body
    return 0;
}

4 个答案:

答案 0 :(得分:2)

通常,您不能返回指向非静态局部变量的指针或引用,因为它们在函数返回时被销毁。使数组静态可以防止它被破坏,但会引入其他问题:如果再次调用该函数,数组将被覆盖,并且从多个线程调用它会导致数据争用。

好消息是,如果数组包含在类类型中,则可以按值返回数组。 C ++ 11有一个标准类型:

std::array<float, 3> doubleEachElement(float *arr);

如果您过去陷入困境,只需定义自己的类型,例如

struct my_array {
    float values[3];
};

答案 1 :(得分:1)

函数的任何局部变量(如果没有静态存储持续时间)在退出函数后不活动。那就是它被认为是被摧毁了。阵列占用的内存可以被覆盖。因此指针将具有无效值,程序将具有未定义的行为。

答案 2 :(得分:0)

你回答了自己的问题 -

  

在退出函数体时会破坏局部变量

那么为什么要将指针返回到被销毁的东西呢?这会导致未定义的行为,您肯定希望避免这种行为。

要从函数返回数组,您应该使用new运算符分配内存,然后返回指针。

答案 3 :(得分:0)

有三种方法可以分配数组存储:

  • 在堆栈上
  • 静态片段中的
  • 在堆中

某些变量可以在CPU寄存器中分配,但不能在数组中分配。)

如果在函数内声明数组,但未将其标记为静态,则将在堆栈上分配。这意味着,实际上,编译器会在调用函数时将堆栈指针移动到数组的大小。并确保在函数返回时将堆栈指针重新回退,使得数组占用的内存可用于将来的函数调用。

执行程序时,会立即分配静态内存。并且在程序终止之前不会回收。因此,如果将数组标记为静态,编译器将在静态段中保留内存,因此您可以安全地从函数返回其地址。

如果你想在堆上分配一些东西,你需要使用malloc / free或new / delete操作符。这样你就可以在一个地方分配内存并在另一个地方释放它。虽然,使用标准容器(如std :: vector)更好。