web-dev-qa-db-ja.com

&xの代わりにaddressof(x)を使用する場合

オブジェクトのアドレスを取得するときに_&x_ではなくaddressof(x)が必要かどうかをどのように判断しますか?


質問は混乱しているようですので、明確にする必要があります:

addressofは明らかに、オーバーロードされたaddress-of演算子をバイパスします。 私はすでにそれを知っています。

私が知りたいのは:
それが本当にやりたいことかどうかはどうやってわかりますか?(特にテンプレート内などの場合)

_&_の代わりにaddressofが必要な場合を理解するのに役立つ何らかの「ルール」はありますか?
結局、どちらもオブジェクトの「アドレス」を返すので、いつどちらを使用すればよいですか?

62
user541686

必要なときにstd::addressofを使用します。悲しいことに、「必要なとき」には、テンプレートコードで作業していて、不明な型TまたはT&の変数をその変数のメモリへの正直な神のポインタにしたい場合が含まれます。

C++委員会は(ほとんど正当な目的で)参照演算子のオーバーロードを愚かに許可したため、ユーザーが実際のポインターを取得するために参照演算子を使用できない型でテンプレートをインスタンス化することは可能です。 std::addressofは、この疑わしいC++機能を使用するユーザーを回避して、言語が最初から機能することを保証する必要があることを実行する方法です。

要するに、それは言語の愚かさのためのライブラリの修正です。ユーザーがコードを改ざんできないようにする場合は、&ではなくテンプレートコードで使用します。ユーザーがこの不自然な機能を使用しないと信頼できる場合は、&を使用できます。

77
Nicol Bolas

オーバーロードされた単項operator&を含むユーザー定義型であり、そのアドレスが必要な場合は、addressofを使用します。

常に&を使用するべきだと思います。そうしないと、オーバーロードの目的に反するからです。 Unlessもちろん、オーバーロードで意味のあることをします。その場合、addressof(クラスの外では、 this)を使用するだけですが、自分が何をしているかを十分に確認する必要があります。

詳細は次のとおりです。クラスの外でoperator&をオーバーロードしたい場合は(できます)、する必要がありますaddressofを使用してアドレスを返します。それ以外の場合は、無限再帰になります。

struct Class
{
   virtual ~Class() {}
   int x;
};

void* operator&(const Class& x)
{
    //return &x; <---- infinite recursion
    return addressof(x) + 4; //I know this isn't safe
                             //but I also know the intrinsics of my compiler
                             //and platform to know this will actually return
                             //the address to the first data member
}

これは安全ではないことはわかっています。

10
Luchian Grigore

私の意見のみ:

あなたがクラスとそのインターフェースを設計しているチームの一員でない限り、決して。個人的には、その演算子をオーバーロードする正当な理由を見たことがありません。しかし、誰かが意味のあるクラスを設計し、そのクラスがパブリックでの消費を意図している(つまり、クラスが特定のライブラリでのみ内部的に使用されるものではない)と想定した場合、そのクラスは通常のコードで機能すると期待します&が「アドレス」を意味することを当然期待しています。演算子をオーバーロードするクラスがそのような賢明な方法で設計されていない場合、そのクラス、ピリオドは使用しません。そのクラスが壊れているか、それが属しているライブラリの外部で使用することを意図していないためです。

7

アドレスのoperator&オーバーロードの結果ではなく、オブジェクトの実際のアドレスを知りたい場合に使用します。

7
juanchopanza

結局、どちらもオブジェクトの「アドレス」を返すので、いつどちらを使用すればよいのでしょうか。

オーバーロードされたoperator&はオブジェクトの「アドレス」であり、そうでない可能性があります。クラス作成者がオブジェクトをオーバーロードする必要がなかった可能性があります。別の型を返すためにオーバーロードしたり、人々がそのアドレスを取得するのを不当に防止しようとしている場合はvoidを返したりする可能性もあります。

mightがオーバーロードされているオブジェクトへのポインタが必要な場合&(たとえば、型がテンプレートパラメータであるため、不明なため)std::addressofまたは、テンプレートがオブジェクトの実際のアドレスを正しいタイプとして返​​さないタイプをサポートしていないことを文書化します。

6
Jonathan Wakely