この質問は、次の質問に対するフォローアップの質問として意図されています: C++ におけるポインター変数と参照変数の違いは何ですか?
回答とstackoverflowで見つけたいくつかのさらなる議論を読んだことで、コンパイラは参照渡しをポインタ渡しと同じように扱うべきであり、参照は構文糖に過ぎないことがわかりました。バイナリ互換性を考慮して違いがあるかどうか、まだ把握できていないことが 1 つあります。
私たちの (マルチプラットフォーム) フレームワークでは、リリース ビルドとデバッグ ビルドの間 (およびフレームワークの異なるリリース間) でバイナリ互換性を保つ必要があります。特に、デバッグ モードでビルドするバイナリは、リリース ビルドで使用できる必要があり、その逆も同様です。これを実現するために、インターフェイスでは純粋な抽象クラスと POD のみを使用します。
次のコードを検討してください。
class IMediaSerializable
{
public:
virtual tResult Serialize(int flags,
ISerializer* pSerializer,
IException** __exception_ptr) = 0;
//[…]
};
ISerializer
IException
また、純粋な抽象クラスでもあります。ISerializer
既存のオブジェクトを指す必要があるため、常に NULL ポインター チェックを実行する必要があります。IException
ポインターが指すアドレスを変更する必要がある、ある種の例外処理を実装します。このため、ポインタからポインタへのポインタを使用しますが、NULL ポインタもチェックする必要があります。
コードをより明確にし、不要な実行時チェックを取り除くために、参照渡しを使用してこのコードを書き直します。
class IMediaSerializable
{
public:
virtual tResult Serialize(int flags,
ISerializer& pSerializer,
IException*& __exception_ptr) = 0;
//[…]
};
これで問題なく動作するようです。しかし、これが依然としてバイナリ互換性の要件を満たしているかどうかという疑問が残ります。
更新: 物事を明確にするために:この質問は、コードのポインター渡しバージョンと参照渡しバージョンの間のバイナリ互換性に関するものではありません。これがバイナリ互換でないことはわかっています。実際、バイナリの互換性を気にせずに、ポインター渡しではなく参照渡しを使用することを検討している API を再設計する機会があります (新しいメジャー リリース)。問題は、コードの参照渡しバージョンのみを使用する場合のバイナリ互換性についてです。