32

以前は の存在に気づいていなかったstd::addressofので、それが存在する理由は私には理にかなっています。オーバーロードされた の存在下でアドレスを取得する方法としてoperator&。ただし、実装はやや不透明です。からgcc 4.7.1:

template<typename _Tp>
inline _Tp*
__addressof(_Tp& __r) _GLIBCXX_NOEXCEPT
{
  return reinterpret_cast<_Tp*>
(&const_cast<char&>(reinterpret_cast<const volatile char&>(__r)));
}

reinterpret_cast<_Tp*>明らかです。あとは黒魔術。誰かがこれが実際にどのように機能するかを分析できますか?

4

4 に答える 4

10

短いバージョン:

operator&はオーバーロードできませんcharcharそのため、真のアドレスであることが保証されているものを取得するために、型が参照にキャストされています。

const_castとの制限により、その変換は 2 つのキャストで行われreinterpret_castます。

より長いバージョン:

3 つの連続したキャストを実行しています。

reinterpret_cast<const volatile char&>

これは効果的に にキャストしていchar&ます。constandはorである可能性があるvolatileためのみ存在し、それらを追加することはできますが、削除することはできません。_Tpconstvolatilereinterpret_cast

const_cast<char&>

constvolatileが削除されました 。const_castそうするかもしれません。

reinterpret_cast<_Tp*>(&result)

ここで、アドレスが取得され、型が元の型へのポインターに変換されます。

于 2013-04-24T14:56:01.697 に答える
6

裏返しに:

  • 最初に__r型を aにキャストしますconst volatile char&:ファンキーなことchar&を行うオーバーロードを確実に持たない型であるという理由だけで、 a にキャストしています。operator&が存在するのconst volatileは、これらが制限であるためです。追加することはできますが、削除することはできませんreinterpret_cast_Tpすでにconstand/orvolatileである可能性があり、その場合、このキャストでは一方または両方が必要でした。そうでない場合、キャストはそれらを不必要に追加しただけですが、最も制限的なキャスト用に書かれています。

  • 次に、 を取り除くには、次の部分につながるconst volatileが必要です... .const_castconst_cast<char&>

  • そこから、単にアドレスを取得し、それを必要な型 a にキャストするだけです_Tp*。および/またはである_Tp可能性があることに注意してください。これは、これらのものをこの時点で追加し直すことができることを意味します。constvolatile

于 2013-04-24T14:56:31.017 に答える