为什么'this'是指针而不是引用?

206
我正在阅读这个问题的答案C++ pros and cons,在阅读评论时产生了疑问。

程序员经常会感到困惑,“this”是一个指针而不是引用。另一个困惑是为什么“hello”不是std :: string类型,但在数组转换为指针后评估为char const *(指针)– Johannes Schaub - litb Dec 22 '08 at 1:56

这只表明它不使用与其他(较新的)语言相同的约定。– le dorfier Dec 22 '08 at 3:35

虽然我不明白第一个示例中有关大小的信息与任何事情有关系,但我认为“this”是一个相当微不足道的问题。还有一些未定义行为示例中的错误需要纠正。 :) 指针根本不能指向分配的内存之外– jalf Dec 22 '08 at 4:18

这是一个常量指针吗?– yesraaj Dec 22 '08 at 6:35

如果方法是const int getFoo() const; <-在getFoo的范围内,“this”是常量,并且因此只读。这可以防止错误并为调用者提供某种级别的保证,表明对象不会更改。– Doug T. Dec 22 '08 at 16:42

你不能重新分配“this”。即你不能做“this = &other;”,因为这是一个rvalue。但是它的类型是T *,而不是T const。也就是说,它是一个非常量指针。如果您在const方法中,则它是指向常量的指针。T const。但指针本身是非常量的– Johannes Schaub - litb Dec 22 '08 at 17:53

将“this”视为这样:#define this(this_ + 0),其中编译器创建“this_”作为指向对象的指针,并将“this”作为关键字。您无法分配“this”,因为(this_ + 0)是rvalue。当然,它并不是这样的(没有这样的宏),但它可以帮助理解– Johannes Schaub - litb Dec 22 '08 at 17:55

我的问题是,为什么this是一个指针而不是引用?有什么特殊的原因使它成为指针吗?


以下是一些进一步的论据,说明this是一个引用是有道理的:

  • 考虑 More Effective C++ 中的项目1:在确保存在有效对象(而非NULL)时使用引用(我的理解)。
  • 此外,相对于指针来说,引用更加安全(因为我们无法通过错误指针破坏内存)。
  • 第三,访问引用的语法(.)比访问指针(->(*))更加简洁和舒适。

6
这个“hack”能实现什么效果?this不是默认为true吗? - iFreilicht
6
@paulm 我不认为那是有效的 C++。在空指针上调用对象的方法会导致未定义行为。 - antred
5
可能在某些情况下这个方法可行,但是想象一下如果这个方法是虚拟的,没有对象如何进行虚函数表查找? - Jason C
4
如果你在实际代码中看到了这个问题,请立刻放弃!那是未定义行为。 - Alice
8
我会留下这个内容...(来自MFC的afxwin2.inl): _AFXWIN_INLINE HWND CWnd::GetSafeHwnd() const { return this == NULL ? NULL : m_hWnd; } 翻译后内容:此处仅供参考...(源自MFC的afxwin2.inl):_AFXWIN_INLINE HWND CWnd::GetSafeHwnd() const { return this == NULL ? NULL : m_hWnd; } - Christopher Oicles
显示剩余5条评论
3个回答

198

当C++语言刚开始发展时,早期版本中没有引用,只有指针。引用是在加入运算符重载时添加的,因为它需要引用来保证一致性。

this的一个用途是让对象获取指向自身的指针。如果它是一个引用,我们就必须写&this。另一方面,当我们编写赋值操作符时,我们必须写return *this,这看起来会简单些。return this。因此,如果你从零开始设计,你可以辩论其中的任一种方式。但是,C++逐渐地根据用户反馈不断演变(就像大多数成功的事物一样)。与this是引用或指针相关的微小优势/劣势相比,向后兼容的价值完全压倒了一切。


5
嗯,一个对象获得对自身的引用也经常很有用。我认为这是更常见的用法。无论如何,主要原因就像你所说的,当创建“this”指针时,引用并不存在。 - jalf
25
如果这是一个参考,要想通过重载operator &来完成有用的操作将会很困难。必须有一些特殊的语法来获取此对象的地址,而不经过operator & - Omnifarious
11
@conio - 下次你接近C++编译器时,可能需要检查一下! :) 类似这样:int n = 5; int &r = n; int *p = &r; std::cout << *p; - Daniel Earwicker
15
你可以写&reinterpret_cast<char&>(this);来获取重载operator&的真实地址(事实上,这就是boost::addressof所做的)。 - Johannes Schaub - litb
12
既然this为null没有任何意义,所以我认为一个引用更加适合。 - Ponkadoodle
显示剩余7条评论

130

来晚了一点……直接引用权威人士Bjarne Stroustrup的话(摘自或引自《C++设计与演化》一书):在这里

this”为什么不是一个引用?

因为“this”是在引入引用之前引入C++(实际上是在引入类似C的类)中的。此外,我选择使用“this”遵循Simula的用法,而不是(后来的)Smalltalk使用的“self”。


2
是的,对于与其他编程语言的一致性来说,self 会很好,不过没关系。 - pilkch
7
self 可以作为一个关键字,起到类似 *this 的作用。 - jxh
6
#define self *this 翻译为中文:#定义 self 为 *this - David Callanan
1
#define self (*this) - John Källén

10

除了其他答案,由于Deducing thisC++23中的一个功能,因此将可以对调用成员函数的对象进行引用(而不是this指针):

struct Foo {
  void bar(this Foo& self) {
    // self is a reference to Foo
  }
};

int main() {
  Foo foo;
  foo.bar();
}

1
任何一种语言,如果你可以写出像 this Self&& self 这样的东西,就会有一些固有的问题... 看起来随着所有新的 C++ 修订版的推出,他们正在不断添加更多只是修复语言本身问题而非增加功能的东西。forward_likedeclvalto_addresslaunderstart_lifetime_asenable_ifvoid_tdestroying_delete_treference_wrappermove_only_functionbind_front/back 等等。 - tmlen
这些东西的添加为应用程序提供了更精细的控制,特别是在真正重要的时候,以及更安全、更容易完成那些本来很麻烦的任务。C++首先是一种系统语言。对一切的绝对控制是绝对必要的。因此,它自然会有很多不太干净的接口,因为系统本来就是不太干净的地方。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接