タイトルで述べたように、'this'
ポインターのタイプについて知りたいのですが。
私はプロジェクトに取り組んでおり、VC++ 2008を使用するWindowsでは'this'
ポインタのタイプが"ClassName * const this"
であることに気付きました。まあ、このポインタを定数ポインター。ありがとう。
このポインターのタイプは、クラスClassName
の非constメソッドまたはconstメソッドの内部で検査されるかどうかに応じて、ClassName *
またはconst ClassName *
のいずれかになります。ポインターthis
は左辺値ではありません。
class ClassName {
void foo() {
// here `this` has `ClassName *` type
}
void bar() const {
// here `this` has `const ClassName *` type
}
};
上記の観察は誤解を招くものです。ポインタthis
はlvalueではない(つまり、ClassName * const
型を持つことができない、つまり、 const
は*
の右側にあります。ポインター型の左辺値以外は、constまたはnon-constにすることはできません。 C++言語には、そのような概念はありません。あなたが観察したものは、特定のコンパイラの内部の奇妙なものでなければなりません。正式には正しくありません。
言語仕様からの関連する引用は次のとおりです(強調は私のものです)
9.3.2 this thisポインタ
非静的(9.3)メンバー関数の本体では、キーワードthisはprvalue式であり、その値は、関数が呼び出されるオブジェクトのアドレスです。 クラスXのメンバー関数におけるthisの型はX *です。メンバー関数がconstと宣言されている場合、これの型はconst X *です。メンバー関数がvolatileと宣言されている場合、これの型はvolatile X *、およびメンバー関数がconst volatileと宣言されている場合、これのタイプはconst volatile X *です。 [注:したがって、constメンバー関数では、関数が呼び出されるオブジェクトはconstを介してアクセスされますアクセスパス。 —エンドノート]
C++ 98/C++ 03時代に戻って、いくつかのコンパイラが内部実装トリックを使用したことは何の価値もありません。それらはthis
ポインタを定数ポインタとして解釈しました。クラスClassName
の非定数メソッドのClassName *const
。これは明らかに彼らがthis
の変更不可性を保証するのに役立ちました。 GCCとMSVCはこの手法を使用したことが知られています。言語レベルではthis
は左辺値ではなく、その一貫性は検出できなかったため、これは無害なトリックでした。その余分なconst
は、通常、コンパイラーによって発行された診断メッセージでのみ明らかになります。
ただし、C++ 11での右辺値参照の出現により、const
の型でこの余分なthis
を検出できるようになりました。たとえば、次のコードはC++ 11で有効です。
struct S
{
void foo() { S *&&r = this; }
};
それでも、通常は前述のトリックを使用する実装ではコンパイルできません。その後、GCCはこの手法を放棄しました。 MSVC++は引き続きそれを使用します(VS2017以降)。これにより、上記の完全に有効なコードがMSVC++でコンパイルできなくなります。
Constは、ポインタが指すものを変更できないことを意味します。
ClassName *const
とは大きく異なります
const ClassName *
後者はオブジェクトへのポインターであり、オブジェクトは(とにかくポインターを使用して)変更できません。前者は、少なくとも厄介なキャストに頼らない限り、別のオブジェクト(またはNULL)に再ポイントできないポインターです。
もちろん組み合わせもあります:
const ClassName *const
これは、別のものを指すように変更できないポインターであり、また、それが指すオブジェクトを変更するために使用することもできません。
コンパイラーがthis
ポインターをconstとして表示する理由については、this
を最初のオブジェクト以外のオブジェクトにポイントすることはお勧めできません。
上記で多くの議論があり、メインポストは正解を提示しませんでした。人々はコメントを掘らないかもしれないので、メインポート(PS)として共有する方が良いです。
UbuntuとVC++で調査を行いましたが、正しい出力がありません(typeid(X).name
を使用)。
クラス型Xのメンバー関数に対するこのポインターの型は、X * constです。メンバー関数がconst修飾子で宣言されている場合、クラスXのそのメンバー関数のthisポインターの型はconst X * constです。 MSDNリンク
概念的にはこれも正しいです。通常のメンバー関数は "X * const"であるため、l値ではありません(その内容を変更できないため)。