我对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;
}
我的问题是为什么编译器deosn报告错误,我在SetX和SetY函数中返回一个this指针,但是没有将返回类型声明为指针?
答案 0 :(得分:3)
这是因为您正在返回*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;
}
正如您所看到的,this
指向的对象位于setY
方法中与main
相比的不同地址。这是因为该对象被复制到setY
方法的堆栈框架中 - 因此在setX
和setY
内,您正在处理{{1}的副本 }}
如果您正在执行obj1
,则基本上复制对象 obj1.setX(10).setY(20);
并在obj1
中使用它,然后在setX
中使用返回对象{ {1}}。如果要保存最后一个副本,则必须将其重新分配给setX
。
您解决问题的方法有效,但效率极低。描述正在发生的事情的最后一段是不正确的。调用setx并使用obj1。调用sety并使用obj1的副本。然后为obj1分配由sety返回的obj1副本的副本。地址不会改变,因为obj1的存储被覆盖,而不是被替换。添加复制构造函数和赋值运算符,您可以观察到实际发生的情况。推荐的解决方案是根据@πάνταῥεῖ的答案使用对整个相同对象的引用和链接。 - user4581301
答案 1 :(得分:2)
我的问题是为什么编译器deosn报告错误,我在SetX和SetY函数中返回this指针,但是没有将返回类型声明为指针?
它是完全有效的语法,因此编译器不应该返回错误消息。问题是您使用的是this*
副本并返回了返回类型。
要正确链接操作以对原始实例进行操作,请返回对this
:
Test& setX(int a) { x = a; return *this; }
// ^
Test& setY(int b) { y = b; return *this; }
// ^
否则,您将返回班级中不相关的副本。