【发布时间】:2021-08-03 03:42:19
【问题描述】:
我知道这已经是一个常见问题,但我更好奇指针和引用在较低级别的行为(例如编译器如何处理它们,以及它们在内存中的样子),但我没有找不到解决办法,所以我来了。
起初我想知道是否可以将数组作为参数传递而不被强制转换(或衰减)到指针中。进一步来说。我想要以下代码:
void func(?? arr) {
cout << sizeof(arr) << "\n";
}
int main() {
int arr[4];
func(arr);
return 0;
}
输出16而不是8,这是一个指针的大小。
第一次尝试
void func(int arr[4]);
希望指定大小可以保留数组的属性,但arr还是被当作指针来处理。
然后我发现了一些有用的东西:
void func(int (&arr)[4]);
但这让我很困惑。
过去我的印象是,虽然指针和引用的含义不同,但在实际执行代码时,它们的行为是相同的。
我从自己的实验中得到了这个想法:
void swap(int* a, int* b) {
int c = *a;
*a = *b;
*b = c;
}
int main() {
int a = 3, b = 5;
swap(&a, &b);
}
和
void swap(int& a, int& b) {
int c = a;
a = b;
b = c;
}
int main() {
int a = 3, b = 5;
swap(a, b);
}
被编译成相同的汇编代码,也是如此
int main() {
int a = 3;
int& b = a;
b = 127;
return 0;
}
和
int main() {
int a = 3;
int* b = &a;
*b = 127;
return 0;
}
我关闭了优化,g++和clang++都显示了这个结果。
也是我对第一个实验的想法:
在考虑内存时,swap 应该有自己的堆栈帧和局部变量。将swap 中的a 直接映射到main 中的a 对我来说没有多大意义。就好像main 中的a 神奇地出现在了不应该属于它的swap 的堆栈帧中。所以它被编译成与指针版本相同的程序集并不让我感到惊讶。也许引用的魔力是通过引擎盖下的指针实现的。但现在我不确定了。
那么编译器如何处理引用以及引用在内存中的样子?它们是占据空间的变量吗?我该如何解释我的实验结果和数组问题?
【问题讨论】:
-
你的问题实际上是几个不同问题的组合,每个问题都是重复的。职业培训中心。
-
听起来你可以使用good C++ book。他们应该深入研究这一点
-
指针和引用如何在底层工作是一个实现细节。通常,它们都通过存储内存地址来工作。您的数组参考代码给出不同大小的原因与这些细节无关。该行为是标准规定的,并且无论实施如何都将以这种方式工作。您看到的实际值可能会有所不同,但带有数组参数的示例将始终返回指针的大小,而引用数组的示例将始终返回实际数组的大小。
-
像
int arr[4]这样的函数参数是语言告诉你的一个大谎言。它是从 C 继承的一种行为,为了向后兼容而保留。数组类型参数始终只是变相的指针。它与int * arr相同,这就是为什么您获得指针大小而不是数组大小的原因。这会引起很多混乱,特别是导致新用户认为数组只是指针。 -
旁注:C++ 不需要堆栈。它们只是另一个实现细节,尽管是迄今为止最常见的实现细节。