【问题标题】:'this' pointer behaviour in c++C ++中的“this”指针行为
【发布时间】:2016-06-08 16:35:45
【问题描述】:

我对C++中的这个指针有一个基本的了解。学习的时候遇到了如下代码:

#include<iostream>
using namespace std;

class Test
{
private:
int x;
int y;
public:
//Test (int x = 0, int y = 0) { this->x = x; this->y = y; }
Test setX(int a) { x = a; return *this; }
Test setY(int b) { y = b; return *this; }
void print() { cout << "x = " << x << " y = " << y << endl; }
};

int main()
{
Test obj1;
obj1.setX(10).setY(20);
obj1.print();
return 0;
}

我的问题是为什么编译器没有报告错误,我在 SetX 和 SetY 函数中返回 this 指针,但没有将返回类型声明为指针?

【问题讨论】:

  • this 的类型为 Test*,*this 的类型为 Test。
  • setX 和 setY 应该返回一个引用 (Test&amp;) 以使 main 中的代码正常工作。否则它将修改一个临时副本。
  • @interjay..只是想要一个更清晰的解释..如果我们已经返回 Test 类型,那么什么是临时变量而不是原始变量
  • 如果您返回Test,那么它将返回对象的副本,并且对该副本所做的任何修改都将丢失。如果您返回Test&amp;,那么它将返回对同一对象的引用。这就像Test obj2=obj1(给出两个不同的对象)和Test &amp;obj2=obj1(两个变量引用同一个对象)之间的区别。
  • @OMKAR 在学习时遇到了以下代码: -- 我的雷达检测到您从获得此代码的任何地方复制了错误的示例。您给出的示例是做一些称为“函数链接”的事情,这是一个众所周知的习语。鉴于此,我怀疑您遇到的示例是返回 Test 而不是 Test&amp;。无论您在哪里获得此示例,作者都不会犯这样的错误(返回 Test 而不是 Test&amp;)。如果他们这样做了,请找到更好的材料来获取您的 C++ 示例。

标签: c++ pointers this


【解决方案1】:

这是因为您返回的是 *this 而不是 this。

this 是指向Test 类型对象的指针。这意味着this-变量基本上保存了存储对象的地址。要访问this 指向的对象,请使用*。

因此,您返回的是 this 指针指向的实际对象。


编辑

您的代码无法按您希望的方式运行的问题是由于您正在堆栈上工作这一事实造成的。

我们来看看地址:

#include<iostream>
using namespace std;

class Test
{
private:
    int x;
    int y;
public:
//Test (int x = 0, int y = 0) { this->x = x; this->y = y; }
    Test setX(int a) { x = a; return *this; }
    Test setY(int b) {
        y = b;
        cout << this << endl; // >> 0x29ff18
        return *this;
    }
    void print() { cout << "x = " << x << " y = " << y << endl; }
};

int main()
{

    Test obj1;
    cout << &obj1 << endl; // >> 0x29ff10
    obj1 = obj1.setX(10).setY(20);
    cout << &obj1 << endl; // >> 0x29ff10
    //obj1.setY(20);
    obj1.print();
    return 0;
}

如您所见,与main 相比,this 指向的对象在您的setY 方法中位于不同的地址。这是因为对象被复制到 setY 方法的堆栈帧中 - 所以在 setX 和 setY 中,您正在使用obj1

的副本

如果你在做obj1.setX(10).setY(20); 你基本上复制对象obj1 并在setX 中使用它,然后setX 的返回对象在setY 中使用。如果要保存最后一个副本,则必须将其重新分配给obj1。

您的问题解决方案有效,但效率极低。最后一段描述正在发生的事情是不正确的。 setx 被调用并使用 obj1。 sety 被调用并使用 obj1 的副本。然后为 obj1 分配 sety 返回的 obj1 的副本。地址不会改变,因为 obj1 的存储被覆盖,而不是被替换。添加一个复制构造函数和一个赋值运算符,你就可以看到真正发生了什么。推荐的解决方案是根据@πάνταῥεῖ 下面的回答在整个过程中使用对同一对象的引用并进行链接。 – 用户4581301

【讨论】:

  • 好的,根据你的回答,如果返回了实际的对象,那么它也应该改变 y 的值。但是上面代码的输出是:x = 10 y = 0
  • @falx 你走错了路。我不知道为什么这会受到如此多的赞成。
  • @πάντα ῥεῖ 我的错在哪里?很高兴知道这一点
  • @πάντα ῥεῖ 我正在解释为什么这种行为会出现这样的背景。所以我在正确的轨道上
  • 您的问题解决方案有效,但效率极低。最后一段描述正在发生的事情是不正确的。 setx 被调用并使用obj1。 sety 被调用并使用obj1 的副本。然后将obj1 分配给sety 返回的obj1 的副本。地址不会改变,因为obj1 的存储被覆盖,而不是被替换。添加一个复制构造函数和一个赋值运算符,你就可以看到真正发生了什么。推荐的解决方案是根据@πάνταῥεῖ 下面的回答在整个过程中使用对同一对象的引用并链接。
【解决方案2】:

我的问题是为什么编译器没有报告错误,我在 SetX 和 SetY 函数中返回 this 指针,但没有将返回类型声明为指针?

这是完全有效的语法,因此编译器不应该返回错误消息。问题是您在返回类型中使用了 this* 的副本。


要正确链接操作以对原始实例进行操作,请返回对 this 的引用:

Test& setX(int a) { x = a; return *this; }
 // ^
Test& setY(int b) { y = b; return *this; }
 // ^

否则,您将返回与您的课程无关的副本。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-25
    • 1970-01-01
    • 2020-04-04
    • 1970-01-01
    • 1970-01-01
    • 2011-02-01
    • 1970-01-01
    相关资源
    最近更新 更多