我的问题类似于一些相关问题,但这些问题的答案并不能解决我的主要困惑。我试着以最简单的形式提出这个问题。
我想返回一个在函数体内定义的数组。由于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;
}
答案 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)更好。