6

私はこのように定義された関数を持っています:

void doSomethingWithCustomer (const Customer &customer);

私の仲間の開発者の1人はそれを次のように呼びました:

Customer *customer = order.getCustomer();
doSomethingWithCustomer (*customer);

残念ながら、getCustomer注文が顧客に関連付けられていない場合、メソッドはnullptrを返す可能性があります。nullptrを返す場合getCustomer、アプリケーションは呼び出し時にクラッシュするのではdoSomethingWithCustomerなく、顧客参照が使用される関数内でクラッシュします。

もちろん、これを書く正しい方法は、最初に顧客がnullptrでないことを確認してから、有効な顧客がいる場合は関数を呼び出すことです。通常、関数/メソッドに参照引数がある場合、関数自体が引数をチェックするのではなく、呼び出し元がその有効性をチェックすることを期待します(ここではそうではありませんでした)。

Visual Studio 2010(およびそれ以前のバージョン)は実際にポインターを渡すことで参照を渡すことを知っていますが、これはC++標準のどこかに示されているのではないかと思います。参照が常にポインターとして渡されると仮定できますか(個人的には、これに依存しませんが、それを知ることは興味深いです)?

Visual Studioに、参照を渡すときに、最初に自動的に逆参照し、呼び出し時にクラッシュする必要があることを伝えることはできますか?(デバッグバージョンでこれを行うだけで十分な場合があります)?

4

6 に答える 6

4

参照がポインタとして渡されると仮定することは有効ですか?

いいえそうではありません。
この規格は、参照をポインタの観点から実装することを義務付けていません。

参照を実際に実装する方法は、実装が決定するために標準が省略している実装の詳細です。これは、リファレンスから予想される動作を説明するだけであり、そのうちの1つは、リファレンスがNULL標準の準拠プログラムに含まれることは決してないということです。

関数パラメーターが時々あると予想されるNULL場合は、それをポインターとして渡す必要があります。

于 2012-11-20T09:30:26.067 に答える
1

いいえ。完全に実装が定義されています。

診断の目的で、パラメーターを検証する小さなコンテナータイプを作成しました。次に、関数/メソッドを宣言します。

void doSomethingWithCustomer(const t_nonnull<const Customer>& pCustomer);

ここで、t_nonnullタイプは構築時にパラメーターを検証しました。ただし、参照を頻繁に使用する方が便利であることがわかりました(IOW、この場合はポインターを返さないでください。顧客が存在しないときに顧客にアクセスするのはエラーだと考えてください)。

于 2012-11-20T09:34:15.057 に答える
1

動作は未定義です。つまり、エラーを発見する特定の方法に頼ることはできません。優れたコンパイラーはコンパイル時に警告を発することができますが、変数の使用方法によっては、別のコンパイラーがエラーを完全にマスクする可能性があります。参照が決してNULLにならないようにするのはあなたの責任です。

于 2012-11-20T09:37:16.767 に答える
1

それは観察可能ではなく、無関係です。このコードを使用するプログラムは、nullポインターを逆参照するため、未定義の動作をします。

于 2012-11-20T13:18:03.840 に答える
0

参照、内部でポインターを使用して実装される場合があります(Javaで発生する場合のように)。しかし、2つ以下の違いはそれらの間で重要です:

  1. デフォルトでは、ポインタを他のオブジェクトに再バインドできます。ただし、参照には、初期化されたオブジェクトとの永続的なバインディングがあります
  2. ポインタには0を割り当てることができますが、参照にはできません

同様T&に、と同等T* constです。

変数の延期についてコンパイラに通知する必要はありません。これは自分で行うためです。

void foo(T&);

T t, *p = 0;
foo(t); // the only way to pass reference
foo(*p); // the only way to pass reference
于 2012-11-20T09:28:42.077 に答える
0

他の人が言っているように、標準は参照がどのように実装されるべきかを課していません。「参照として渡された逆参照NULL」エラーを早期にキャッチするには、関数内でこれを行うことができます。

void doSomethingWithCustomer (const Customer &customer)
{
  assert(&customer);
  //... rest of function
}
于 2012-11-20T09:55:24.003 に答える