我们在学习 C++ 的时候经常被告诫指针不是引用, 引用不是指针.
今天我们来写一段小程序, 来一探究竟.
1. 关于指针
1#include <stdio.h>
2
3void main( void )
4{
5 int a = 20;
6 int * b = &a;
7 (*b) ++;
8 printf(“==== %d ====\r\n”, *b);
9}
10看看我们对它编译后在调试器内的反汇编码:
5: int a = 20;
00401028 mov dword ptr [ebp-4],14h ; // 为变量 a 赋值 14h(也就是十进制的 20), [ebp-4] 就代表变量 a
6: int * b = &a;
0040102F lea eax,[ebp-4] ; // 取得变量 a 的地址
00401032 mov dword ptr [ebp-8],eax ; // 将地址赋值给变量 b; 嗯, 是这个样子, 不离谱
7: (*b) ++;
00401035 mov ecx,dword ptr [ebp-8] ; // [ebp-8] 代表变量 b
00401038 mov edx,dword ptr [ecx] ; // 取得指针 b 的值, 存入 edx 寄存器
0040103A add edx,1 ; // 将 edx 寄存器的值增加 1
0040103D mov eax,dword ptr [ebp-8]
00401040 mov dword ptr [eax],edx ; // 将 edx 的值存回 b 指针所指的值
8: printf(“==== %d ====\r\n”, *b);
00401042 mov ecx,dword ptr [ebp-8]
00401045 mov edx,dword ptr [ecx]
00401047 push edx
00401048 push offset string “==== %d ====\r\n” (0042801c)
0040104D call printf (004012a0)
00401052 add esp,8
9: }
以上汇编码跟我们的常识符合.
2. 关于引用
1#include <stdio.h>
2
3void main( void )
4{
5 int a = 20;
6 int & b = a;
7 b ++;
8 printf(“==== %d ====\r\n”, b);
9}
再来看看相应的汇编码:
5: int a = 20;
00401028 mov dword ptr [ebp-4],14h
6: int & b = a;
0040102F lea eax,[ebp-4]
00401032 mov dword ptr [ebp-8],eax
7: b ++;
00401035 mov ecx,dword ptr [ebp-8]
00401038 mov edx,dword ptr [ecx]
0040103A add edx,1
0040103D mov eax,dword ptr [ebp-8]
00401040 mov dword ptr [eax],edx
8: printf(“==== %d ====\r\n”, b);
00401042 mov ecx,dword ptr [ebp-8]
00401045 mov edx,dword ptr [ecx]
00401047 push edx
00401048 push offset string “==== %d ====\r\n” (0042801c)
0040104D call printf (004012a0)
00401052 add esp,8
9: }
可以看出, 这两段汇编码完全一样.
因此, 可以下结论了, 在汇编层面, 引用和指针是完全一样的东西. 咱们的教科书上的说法仅仅是语言层面的, 编译器的底层实现是有自己的逻辑的.
经过试验, 数组的引用是不能作为函数的参数的, 例子如下:
// 如果定义成如下这样, 将不能通过编译
void RefAsParam(int & aRR[])
{
printf(“==== %d == %d ====\r\n”, aRR[0], sizeof(aRR));
}甚至也不能定义成这样:
void RefAsParam(int & aRR[10])
{
printf(“==== %d == %d ====\r\n”, aRR[0], sizeof(aRR));
}而只能定义成这样:
void RefAsParam(int aRR[])
{
printf(“==== %d == %d ====\r\n”, aRR[0], sizeof(aRR));
}或者这样 void RefAsParam(int aRR[10]), 但其中的sizeof(aRR) 的值等于4, 即一个指针的大小, 而不是 4*10=40 个字节.
能通过编译且sizeof(aRR)等于 40 的的代码列出如下, 这定义的新类型定死了就是 10 个元素的数组, 相当没有灵活性.
#include <stdio.h>
// 只能定义成这样, 一个新类型, 含10个元素的整型数组
typedef int MyArray[10];
void RefAsParam(MyArray & aRR)
{
printf(“==== %d == %d ====\r\n”, aRR[0], sizeof(aRR));
}
void main( void )
{
int a[10] = { 20, 30, 77 }; // 或者像这样: MyArray a = {20, 30, 77};
RefAsParam(a);
}现在, 我们为了元素类型和元素个数的灵活性, 只能玩玩模板了, 看看下面:
#include <stdio.h>
template<typename elemType, size_t nSize>
class CRefAsParam
{
public:
typedef elemType MyArray[nSize];
// 当然, 本函数也可以定义成形如: static const void RefAsParam(const MyArray & aRR)
static void RefAsParam(MyArray & aRR)
{
printf(“==== %d == %d ====\r\n”, aRR[0], sizeof(aRR));
}
};
void main( void )
{
typedef CRefAsParam<int, 10> MyType;
MyType::MyArray a = {20, 30, 77};
MyType::RefAsParam(a);
}这样一来, sizeof(aRR) 值是达到 40 了, 但咱们也玩了相当的奇技淫巧. 跟我们追求的简单,直接,有效简直差了十万八千里.哎~~~
原创文章,转载请注明: 转载自日光博客
本文链接地址: C++ 的指针和引用












