C ++の「参照」と「ポインタ」の違いについては、インターネット上に多くの記事があります。違いについては、「参照をNULLにすることはできません。参照を有効なストレージユニットに関連付ける必要があり、ポインタをNULLにすることができます。 )「しかし、実際のアプリケーションでは、一貫性を維持するために、このルールを脇に置き、人工的に「null参照」を作成します。
多くの場合、「空の参照」は実際に機能するため、「参照を空にすることはできません」という助言は、標準的なセッターによるセンセーショナルな形式主義としてあざけられます。「null参照」の例は次のとおりです。
int * a = NULL; int&b = * a;
したがって、bにアクセスすると、プログラム例外が発生しました。
void f(int&p) { p = 0 ; } f(b);
もちろん、この問題を修正するための判断を加えることができます。
void f(int&p) { if(&p)p = 0 ; }
調子はいかがですか?しかし、それがポインタに置き換えられた場合、入力する文字数はまったく同じです。
void f(int * p) { if(p)* p = 0 ; }
したがって、「参照」を使用するか「ポインタ」を使用するかは、賢明な見方の問題だと思われます。
ただし、ただし。。。。。。
これは本当に同じですか?
より複雑な例を見てみましょう:
// test.cpp #include <iostream> class A { int a; }; クラスB { int b; }; クラスC :パブリック A、パブリック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); 0を返し ます。 }
コンパイルして実行すると、次のことがわかります。
$ ./ テスト 0 0x4
なぜ、&bが0でないのか、つまり「null参照」ではない理由です。現時点では、(&b)が役に立たない場合は、判断が追加されても同じです。
上記がLinux環境であることにお気づきかもしれませんが、Windows環境についてはどうでしょうか。
> test.exe 00000000 00000000
現時点では、「空の参照」は彼の「空」の属性を維持し、WindowsプラットフォームのC ++開発者のみがリラックスできます。
何が起こっていますか、あなたの目はあなたを欺いていますか?多分それはそうですが、CPUは私たちをだましません、私たちはアセンブリコードから本質を見ることができます。Linuxプラットフォームでコンパイルされたコードは次のとおりです。
関数メインのアセンブラコードのダンプ: 0x0804870a <+ 0 >:push %ebp 0x0804870b <+ 1 >:mov %esp、%ebp 0x0804870d <+ 3 >:および$ 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 >:追加$ 0x4、%eax 0x08048729 <+ 31 >:jmp 0x8048730 <main + 38 > 0x0804872b <+ 33 >:mov $ 0x0、%eax 0x08048730 <+ 38 >:mov %eax、(%esp) 0x08048733 <+ 41 >:コール0x80486df <FB(B *)> 0x08048738 <+ 46 >:MOV 0x1cに(%ESP)、%eaxに 0x0804873c <+ 50 >:追加$ 0x4のを、%EAX 0x0804873f <+ 53 >:MOV %EAX 、(%esp) 0x08048742 <+ 56>:コール0x80486b4 <fb(B&)> 0x08048747 <+ 61 >:mov $ 0x0、%eax 0x0804874c <+ 66 >:leave 0x0804874d <+ 67 >:ret
これはWindowsプラットフォーム用です。
wmain: 004114D0 プッシュEBP 004114D1 のMOV EBP、ESP 004114D3 サブESP、0DCh 004114D9の プッシュEBX 004114DAが プッシュESIは 004114DB プッシュEDI 004114DC LEA EDI、[EBP-0DCh] 004114E2 MOV ECX、37H 004114E7 のMOV EAX、0CCCCCCCCh 004114EC 担当者 STOS DWORD PTR ES:[edi] 004114EE mov dword ptr [c]、0 004114F5 mov eax、dword ptr [c] 004114F8 movdword 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
アセンブリコードは自分で勉強することに関心があるので、詳細には触れません。
振り返ってみると、2つのプラットフォームのコンパイラの2つの処理方法には妥当性があります。Windowsプラットフォームはフォールトトレランスを向上させ、Linuxプラットフォームは判断を減らし、参照を処理する際のパフォーマンスを向上させます。これは、WindowsとLinuxの異なる開発コンセプトを漠然と反映しています。
最後に、参照をnullにすることはできません。nullオブジェクトが存在する可能性がある場合は、ポインタを使用してください。
元のリンク:https : //blog.csdn.net/luansxx/article/details/10134139