The difference between "null reference" and "null pointer" in C ++

There are many articles on the Internet that discuss the difference between C ++ "reference" and "pointer". When it comes to the difference, one of them is: "The reference cannot be NULL. The reference must be associated with a legal storage unit, and the pointer can be NULL ) ", But in practical applications, sometimes in order to maintain consistency, we will put aside this rule and artificially create a" null reference ".

In many cases, "empty references" can indeed work, so that the advice that "references cannot be empty" is ridiculed as formalism, just sensationalism by standard setters. An example of a "null reference" is:

int * a = NULL;
int & b = *a;

So when accessing b, the program exception appeared:

void f(int & p)
{
    p = 0;
}
f(b);

Of course, you can add some judgment to fix this problem:

void f(int & p)
{
    if (&p) p = 0;
}

How is it, is it a bit awkward? But if it is replaced with a pointer, the number of characters you want to enter is exactly the same:

void f(int * p)
{
    if (p) *p = 0;
} 

 So, whether to use "reference" or "pointer" seems to be the matter of the wise seeing the benevolent.

 

However, however. . . . . .

 

Is this really the same?

 

Let's take a look at a more complicated example:

// test.cpp

#include <iostream>

class A
{
    int a;
};

class B
{
    int b;
};

class C
: public A, public B
{
    int c;
};

void fb(B & b)
{
    std::cout << &b << std::endl;
}

void fb(B * b)
{
    std::cout << b << std::endl;
}

int main(int argc, char* argv[])
{
    C * c = NULL;

    fb(c);

    fb(*c);

    return 0;
}

Compile and run to see:

$ ./test
0
0x4

Hey, why & b is not 0, that is, it is not a "null reference". At this time, even if the judgment is added, if (& b) is not helpful.

You may have noticed that the above is the linux environment, so what about the windows environment:

>test.exe
00000000
00000000

At this time, the "empty reference" maintains his "empty" attribute, only C ++ developers on the Windows platform can relax.

What is going on, is your eyes deceiving you? Maybe it is, but the CPU will not deceive us, we can see the essence from the assembly code. The following is the code compiled on the Linux platform:

Dump of assembler code for function main:
0x0804870a <+0>: push %ebp
0x0804870b <+1>: mov %esp,%ebp
0x0804870d <+3>: and $0xfffffff0,%esp
0x08048710 <+6>: sub $0x20,%esp
0x08048713 <+9>: movl $0x0,0x1c(%esp)
0x0804871b <+17>: cmpl $0x0,0x1c(%esp)
0x08048720 <+22>: je 0x804872b <main+33>
0x08048722 <+24>: mov 0x1c(%esp),%eax
0x08048726 <+28>: add $0x4,%eax
0x08048729 <+31>: jmp 0x8048730 <main+38>
0x0804872b <+33>: mov $0x0,%eax
0x08048730 <+38>: mov %eax,(%esp)
0x08048733 <+41>: call 0x80486df <fb(B*)>
0x08048738 <+46>: mov 0x1c(%esp),%eax
0x0804873c <+50>: add $0x4,%eax
0x0804873f <+53>: mov %eax,(%esp)
0x08048742 <+56>: call 0x80486b4 <fb(B&)>
0x08048747 <+61>: mov $0x0,%eax
0x0804874c <+66>: leave 
0x0804874d <+67>: ret 

This is for the windows platform:

wmain:
004114D0 push ebp 
004114D1 mov ebp,esp 
004114D3 sub esp,0DCh 
004114D9 push ebx 
004114DA push esi 
004114DB push edi 
004114DC lea edi,[ebp-0DCh] 
004114E2 mov ecx,37h 
004114E7 mov eax,0CCCCCCCCh 
004114EC rep stos dword ptr es:[edi] 
004114EE mov dword ptr [c],0 
004114F5 mov eax,dword ptr [c] 
004114F8 mov dword ptr [rc],eax 
004114FB cmp dword ptr [c],0 
004114FF je wmain+3Fh (41150Fh) 
00411501 mov eax,dword ptr [c] 
00411504 add eax,4 
00411507 mov dword ptr [ebp-0DCh],eax 
0041150D jmp wmain+49h (411519h) 
0041150F mov dword ptr [ebp-0DCh],0 
00411519 mov ecx,dword ptr [ebp-0DCh] 
0041151F push ecx 
00411520 call fb (411118h) 
00411525 add esp,4 
00411528 cmp dword ptr [rc],0 
0041152C je wmain+6Ch (41153Ch) 
0041152E mov eax,dword ptr [rc] 
00411531 add eax,4 
00411534 mov dword ptr [ebp-0DCh],eax 
0041153A jmp wmain+76h (411546h) 
0041153C mov dword ptr [ebp-0DCh],0 
00411546 mov ecx,dword ptr [ebp-0DCh] 
0041154C push ecx 
0041154D call fb (41108Ch) 
00411552 add esp,4 
00411555 xor eax,eax 
00411557 pop edi 
00411558 pop esi 
00411559 pop ebx 
0041155A add esp,0DCh 
00411560 cmp ebp,esp 
00411562 call @ILT+345(__RTC_CheckEsp) (41115Eh) 
00411567 mov esp,ebp 
00411569 pop ebp 
0041156A ret 

The assembly code is interested in studying by myself, so I won't go into details.


Looking back, the two processing methods of the compilers of the two platforms have their reasonableness. The windows platform increases fault tolerance, while the linux platform reduces judgment and increases performance when processing references. This vaguely reflects the different development concepts of windows and linux.

Finally, please remember that references cannot be null, and if there may be null objects, use pointers.


Original link: https://blog.csdn.net/luansxx/article/details/10134139

Guess you like

Origin www.cnblogs.com/2018shawn/p/12724525.html