首页 > 解决方案 > 在作用域之间传递数组变量

问题描述

我的第一个问题。在'maning-up'学习c ++时,我让自己陷入了纠结的范围内。我的理解是函数中定义的变量不应该超出范围。但是我一直像下面这样,它每次都可以正常工作。我错过了什么?

我在 ns1.cpp 中定义了一些内联函数,如下所示:

namespace ns1 {

inline void func1(float x[3]);

}

ns1::func1(float x[3]){

//(do stuff to x)

}

在 class_a.cpp 中很远的函数中,我通常像这样使用:


include "ns1.h"

...

void class_a::func2(){

float f[3];

ns1::func1(f)

//f comes back in great shape! No runtime or compilation errors or anything.

}

我的预感是,要么 a)由于 ns1 中的函数是内联的,因此编译器将 func1 的指令放在 func2 的范围内,并且以某种方式不会导致超出范围的类型错误,或者,b)我很幸运并且之前存在行为问题我。

编辑:我让他的问题太复杂了。为简洁起见,我的意思是“您可以在一个函数/范围内创建变量并将它们发送到另一个函数/不同范围的参数的范围之外吗?”。基于 Mooing Ducks 在下面的回答,我可以看到如果发送了指针并且函数更改了指针指向的数据,数组将如何工作。但是,在一个作用域/函数中创建其他变量类型(如 int、char)并将其作为参数发送到另一个函数是不是很糟糕?

标签: c++

解决方案


C++ 有一个非常愚蠢的怪癖,即函数不能按值将数组作为参数。

inline void func1(float x[3]); //x isn't actually an array :(

通常,所有参数都是值的副本。除了数组。相反,C++ 默默地将所有数组值参数转换为指针。所以实际上是:

inline void func1(float* x);

你甚至会发现sizeof(f)infunc2大约是 12(一个包含 3 个浮点数的数组,每个浮点数约为 4 个字节),而sizeof(x)infunc1大约是 8(一个指针),尽管它们看起来都是相同的类型,这真的如果您不小心,会导致问题。

此外,由于数组可以默默地衰减为指针,func1因此能够通过这个指针修改f变量。func2

void class_a::func2(){
float f[3];
ns1::func1(f); //f decays to a pointer, so it passes a pointer to the first item.

即使对于经验丰富的 C++ 开发人员来说,这也是非常令人惊讶的,这也是为什么我们学会了几乎从不按值传递数组的原因。相反,显式传递一个指针 ( float* x, int size) ,或者一个引用数组 ( float (&x)[3]) ,或者一个std::array( std::array<float,3> x),其中任何一个都可以直观地表现。


有趣的旁注:
void class_a::func2(){
float f[1024];
ns1::func1(f); //f decays to a pointer, so this also compiles :(

所以绝对更喜欢按值避免数组参数。


推荐阅读