能否获取'this'指针的地址?

20

我读到了this是一个纯右值,因此我们不能通过应用&this来获取它的地址。

在我的代码中,我尝试使用引用绑定到this。我想知道哪种方法可以给出this的地址?或者两种方式都不正确?

this究竟是什么?是左值还是右值,是关键字还是其他东西?

void MyString::test_this() const{
    std::cout << "this: " << this << std::endl;
    const MyString * const& this_ref = this;
    std::cout << "thie_ref: " << &this_ref << std::endl;
    const MyString * const&& this_right = this;
    std::cout << "thie_right: " << &this_right << std::endl;
}

//this: 00CFFC14
//thie_ref: 00CFFB14
//thie_right: 00CFFAFC

1
&this_ref :你正在打印指针的地址,而不是指针中存储的地址。 - David Haim
6
@DavidHaim,明确一下,这不仅仅是一个指针;它是指向指针的引用。即const MyString * const& this_ref。取它的地址应该得到被引用的指针的地址。OP正在尝试(出于无法解释的原因)获取&this - WhozCraig
7
知道 "this" 指针的地址有什么意义?我觉得这是一个 XY 问题。你真正想做什么? - Clonk
2
顺便提一下,this 在这方面并不是唯一的。你也不能获取标记为 register 的变量的地址。 - Pete Becker
1
请注意,如果您尝试在同一函数块中再次执行完全相同的操作,例如 const MyString * const& my_ref2 = this;,您将获得不同的指针值。 - aschepler
显示剩余2条评论
4个回答

22

我在想哪个可以给出this的地址?或者两个都是错误的?

两者都不是this的地址,因为C++抽象机器没有为其定义地址。 this就像0一样。你无法获取0的地址,它不是具有存储的实体,只是一个值。那么这个怎么办呢?

int const& i = 0;

它创建一个临时对象,用0进行初始化,然后将引用绑定到该对象。您的代码中发生了完全相同的事情。您创建对不同临时对象的引用,这些对象保存了this的值。

this是一个关键字,代表正在执行成员函数的对象的地址。C++抽象机器不要求它占用存储空间,因此它始终(逻辑上)只是一个普通的值,例如0。

不要求this占用存储空间是有优点的。它允许在ABI上实现C++,其中this在寄存器中传递(通常无法寻址)。如果必须定义&this,即如果this必须是可寻址的,则会排除使用寄存器传递地址的实现。C++标准通常旨在不将实现限制在某种特定方式上。


4
只有在odr-used情况下,如果需要对this进行寻址,就不能使用寄存器来传递地址。不过按照as-if原则,在“优化”期间,编译器已经跳过了许多东西的存储。 - Lightness Races in Orbit
2
@LightnessRacesinOrbit - 是的。但我认为问题在于,ABI必须由成员函数的主体确定(因为这可能会或可能不会使用'this')。然而,调用代码(而且是头文件)通常对函数主体没有了解。在这种情况下,我打赌实现将选择悲观的ABI。我可能会过于简化,因此可能完全错误。 - StoryTeller - Unslander Monica
所以,this_ref和this_right只是复制了指向对象"this"的地址,&this_ref和&this_right只是返回这两个指针的地址,对吗? - Range Hao
@RangeHao - 是的。你查看的地址既不是 this 指针的地址,也不是指向它的指针的地址。 - StoryTeller - Unslander Monica
所以实际上,this 更像是 register T *const this - 你不能取它的地址,也不能修改它。它也不允许为 nullptr,因此像 if(this == nullptr) 这样的检查可以被优化掉:不要用它来递归遍历树/链表。除此之外,它基本上就像一个方法的隐藏额外参数,这正是大多数 ABIs 实现它的方式。 - Peter Cordes
显示剩余2条评论

8
“你不能取得this的地址” 是指,你不能写 &this
你是想要获得由this指针表示的地址,对吗?这就是你第一个输出所做的事情。 this本身并不像MyString* x那样被实现为指针。在这里,x本身在内存中有一个位置,你可以做一些类似&x的操作。但是对于this来说这是不可能的。
最后一个问题的答案是:是的,this是一个关键字。表达式this是一个原始表达式。你可以在C++标准的章节[expr.prim.this]中阅读相关内容。

1
在大多数情况下(对于非虚函数),你可以将this视为语法糖,表示一个持有指向对象的指针的额外参数。但它不允许为nullptr,所以检查终止条件时检查if (this == nullptr) return; 的递归链表或树遍历是有问题的:这个检查可能被优化掉。正如你指出的那样,this不能被取地址,因此即使没有使用 as-if 规则的帮助,在“正常”的 CPU 的 C++ 实现中,它也可以保留在寄存器中。如果 C++ 源代码从未获取它们的地址,则其他对象通常实际上没有地址。 - Peter Cordes

5

this 是一个指针,包含了指向 当前对象 的地址。它不是存储在某个地方的变量(甚至无法改变),是一个具有特殊属性的特殊关键字。

如果您想知道 "当前对象" 的地址,可以在程序中简单地输出如下:

#include<iostream>

using namespace std;

class Test
{
    public:
            void fun()
            {
                    cout << "Address of this :: " << this << endl;
                    void *ptr = this;
                    cout << "Addrss of ptr :: " << ptr << endl;
            }
 };

 int main()
 {
    Test obj;

    cout << "Address of obj :: " << &obj << endl;

    obj.fun();

    return 0;
 }

以下是程序的输出结果:

对象的地址 :: 0x7fffef913627

this的地址 :: 0x7fffef913627

指针的地址 :: 0x7fffef913627

希望这能对您有所帮助!

顺便提一下,你正在打印ptr的值(存储在ptr内部的地址),而不是ptr的地址,那应该是&ptr - Holy semicolon

2

this 关键字的行为基本上相当于 &__self,其中 __self 是一个左值,指定运行成员函数的对象(*this 对象),但不使用重载的 operator&()

因此,&this 将意味着 &&__self,这显然是没有意义的,您不能获取地址的地址,就像您不能获取函数的标量返回值的地址一样:

int fi(); 
int *fpi(); 

无论是 &(fi()) 还是 &(fpi()) 都是非法的,因为返回的 rvalue 是一个标量(可能存储在寄存器中),而作为纯标量值,它没有地址


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