我尝试了这个简单的程序:
int* getElement(int arrayy[], int index) {
return &arrayy[index];
}
int main() {
int arrayy[4]{};
*getElement(arrayy, 2)=50;
std::cout << arrayy[2] << '\n';// here it prints 50 !
return 0;
}
getElement()
将通过指针返回返回我的数组的一个元素的地址,在main中取消引用它,然后更改值。
我想用std::array
代替经典数组来做同样的事情。
int* getElement(std::array<int, 4> arrayy, int index) {
return &arrayy[index];
}
int main() {
std::array<int, 4> arrayy{};
*getElement(arrayy, 2)=50;
std::cout << arrayy[2] << '\n';//here it prints 0 !
return 0;
}
第一个印50,第二个印0!
std::array
是否在调用中按值传递?
在通过复制传递指针的情况下,指向的at值在函数和调用站点中是相同的。 所以第一个程序做了您期望的事情。
在第二个程序中,它是不同的,因为std::array
具有值语义,因此通过副本传递它意味着您也传递了所有底层内存的副本。 如果想要获得与第一个程序相同的效果,则需要通过引用传递std::array
:
int* getElement(std::array<int, 4> &arrayy, int index) {
// ^ reference
return &arrayy[index];
}
注意,在您的第二个程序中的代码中,0
的结果是不保证的。 您正在返回一个指针,该指针指向复制的std::array
中的一个值,当函数返回时,该值将终止。 这将调用未定义的行为。
缺省情况下,C++中的所有内容都按值传递。 即使是传统的数组示例也会按值传递指针。 当然你可以用指针来改变它所指向的东西。
您的代码实际上具有未定义的行为,因为您返回的指针指向已被销毁的对象的内部,即GetElement
的arrayy
参数,该参数在退出函数时被销毁。
如果要按引用传递,则必须请求引用
int* getElement(std::array<int, 4>& arrayy, int index) {
return &arrayy[index];
}
参数类型名称后面的&
起到了很大的作用。
std::array在调用中是否通过值传递?
是的。 这样做(传递并返回对象)的能力本质上是std::array存在的原因。
因此,函数参数是函数的本地参数,您返回一个指向这个本地对象的指针,一旦函数返回,这个指针就变成了无效指针。