【发布时间】:2023-03-18 01:55:01
【问题描述】:
正如标题中提到的,我想知道'this'指针的类型。
我正在做一个项目,我观察到 'this' 指针的类型在使用 VC++ 2008 的 Windows 上是 "ClassName * const this"。好吧,我想知道使 this 指针成为常量的需要/要求是什么指针。谢谢。
【问题讨论】:
标签: c++ class this-pointer
正如标题中提到的,我想知道'this'指针的类型。
我正在做一个项目,我观察到 'this' 指针的类型在使用 VC++ 2008 的 Windows 上是 "ClassName * const this"。好吧,我想知道使 this 指针成为常量的需要/要求是什么指针。谢谢。
【问题讨论】:
标签: c++ class this-pointer
const 意味着你不能改变指针指向的东西。
ClassName *const
与
有很大不同const ClassName *
后者是指向对象的指针,不能修改对象(无论如何使用指针)。前者是一个指针,它不能重新指向另一个对象(也不是 NULL),至少在不采用讨厌的强制转换的情况下是这样。
当然还有组合:
const ClassName *const
这将是一个指针,不能更改为指向其他对象,也不能用于更改它指向的对象。
至于为什么您的编译器将 this 指针显示为 const,确实不鼓励您将 this 指向一个不是它开始时的对象。
【讨论】:
this = ... 或This& p = *this(假设p 不是const)。
5 也不能更改或分配给。你不能做5 = 3。但是,5 的类型是int。它是int 而不是const int。说5 具有const int 类型是不正确的。这同样适用于this 指针。它不是左值(就像5 不是左值一样)。不是左值的东西不能是 const 或非常量。因此this指针不能是const,以上分析从形式上看是完全不正确的。
const ClassName *,我更喜欢ClassName const *。与ClassName const * const 到const ClassName * const 相同。从右到左阅读,很容易看出 const 的应用位置。
此指针的类型是ClassName * 或const ClassName *,取决于它是在ClassName 类的非常量方法还是常量方法中检查。指针this 不是左值。
class ClassName {
void foo() {
// here `this` has `ClassName *` type
}
void bar() const {
// here `this` has `const ClassName *` type
}
};
您上面提到的观察结果具有误导性。指针this 不是左值,这意味着它不可能有ClassName * const 类型,即不可能在* 的右侧有一个const。指针类型的非左值不能是 const 或非常量。 C++ 语言中根本没有这样的概念。您观察到的一定是特定编译器的内部怪癖。形式上是不正确的。
以下是语言规范中的相关引用(重点是我的)
9.3.2 this 指针
在非静态 (9.3) 成员函数的主体中,关键字 this 是 prvalue 表达式,其值是对象的地址 该函数被调用。 成员函数中this的类型 X 类是 X*。如果成员函数声明为 const,则其类型 this 是 const X*,如果成员函数声明为 volatile,则 this 的类型是 volatile X*,并且如果声明了成员函数 const volatile, this 的类型是 const volatile X*。 [注意:因此在 一个 const 成员函数,调用该函数的对象 通过 const 访问路径访问。 ——尾注]
在 C++98/C++03 时代,几个编译器使用内部实现技巧是毫无价值的:他们将 this 指针解释为常量指针,例如ClassName *const 在类 ClassName 的非常量方法中。这显然有助于他们确保this 的不可修改性。众所周知,GCC 和 MSVC 已经使用了该技术。这是一个无害的技巧,因为在语言级别 this 不是左值,并且它的 constness 是不可检测的。额外的const 通常只会在编译器发出的诊断消息中显示出来。
但是,随着 C++11 中右值引用的出现,可以在 this 类型上检测到这个额外的 const。例如,以下代码在 C++11 中有效
struct S
{
void foo() { S *&&r = this; }
};
然而,它通常无法在仍然使用上述技巧的实现中编译。 GCC 已经放弃了这项技术。 MSVC++ 仍然使用它(自 VS2017 起),这会阻止上述完全有效的代码在 MSVC++ 中编译。
【讨论】:
ClassName 类的非常量方法中。好吧,我使用 VC++ 智能感知来了解类型,当您滚动变量时它会显示类型。这可能是我收到错误类型信息的可能原因吗?
this 类型。 IE。如果您使用typeid 来检查this 的类型,则* 右侧不会有const。
typeid 进行了检查,并得到了预期的正确类型。
this 可能有一个右值指针类型,如果对象是像ClassName().call() 这样的 tmp obj。
this 是“常量指针”总是不正确的。同样,this 是一个标量类型的右值。标量类型的右值不能是 const 或非常量。第四版是2001年出版的,比较老了。检查以后的版本可能是有意义的。错误可能会在那里修复。
摘自 C++ Primer 第 4 版:“在普通的 nonconst 成员函数中,this 的类型是 const pointer 到 class 类型。我们可以更改 this 指向的值但不能改变this持有的地址。在const成员函数中,this的类型是const pointer到const class类型的对象。我们既不能改变this的对象点也不是this 持有的地址。”这意味着 VC++ intellisense 显示的任何内容都是正确的。
【讨论】:
this 指针是一个右值(参见语言标准中的 9.3.2/1)。非类右值不能有 const 限定类型(参见语言标准中的 3.10/9)。任何一本书声称的内容都是无关紧要的,无论是谁写的。如果某些书籍与语言规范相矛盾,则该书籍有误。
this 有一个常量指针类型。然而,当 C++98 标准最终定稿时,情况就不再如此了。你的书要么已经过时,要么就是错误的。
上面有很多讨论,主要帖子没有给出正确的答案。 人们可能不会挖 cmets,所以最好作为主要端口(PS)共享。
我在 Ubuntu 和 VC++ 上做了一些调查,但没有正确的输出(使用 typeid(X).name)。
类类型 X 的成员函数的 this 指针的类型是 X* const。如果成员函数用 const 限定符声明,则类 X 的该成员函数的 this 指针的类型为 const X* const。 MSDN link
从概念上讲这也是正确的,因为普通的成员函数是“X* const”,这就是它不是左值的原因(因为你不能改变它的内容)。
【讨论】: