c++通过引用和此对象传递

C++ pass by reference and this object

本文关键字:对象 引用 c++      更新时间:2023-10-16

为什么答案是"OK"?

class CTest {
public:
    int isitme(CTest& cobj);
};
int CTest::isitme(CTest &cobj)
{
    if(&cobj == this)
    {
        return true;
    }
    else
    {
        return false;
    }
}
int main()
{
    CTest a;
    CTest *b = &a;
    if(b->isitme(a))
    {
        cout<<"OK";
    }else
    {
        cout<<"not OK";
    }
    return 0;
}

因为成员函数隐式地接收一个指向调用它的对象的指针作为实参。该指针在函数体中作为this指针可用。

所以当你这样做的时候:

b->isitme(a)

成员函数isitme() 隐式地接收指针b作为参数,该指针将被视为函数内部的this指针。

由于b指向a,因此this将指向a(毕竟,您是通过指针b在对象a上调用成员函数isitme())。

由于a是作为显式参数传递的,因此a也是引用cobj绑定的对象。因此,取cobj的地址就得到了a的地址。这反过来意味着,表达式:

//  Address of "a": "cobj" is bound to argument "a" in the function call
//  vvvvv
    &cobj == this
//           ^^^^ 
//           Address of "a": the function is called through a pointer to "a"

求值为true

简短的回答是b是一个指向a的指针——它们都指向同一个实际对象,所以当你比较这"两个"对象的地址时,它们比较起来是相等的。

还有一些东西确实需要指出,虽然它更像是评论而不是回答,但它不适合放在评论中,所以…

int CTest::isitme(CTest &cobj)
{
    if(&cobj == this)
    {
        return true;
    }
    else
    {
        return false;
    }
}

老实说,这是相当糟糕的代码。因为它实际上返回的是一个bool,所以你应该声明它返回一个bool值。直接返回比较的结果也要好得多。您还应该阅读一些关于"const正确性"的内容。考虑到这些因素,您的函数最终看起来更像这样:

bool CTest::isitme(CTest const &cobj) const {
    return this == &cobj;
}

这里有两件事。

首先,只分配了一个CTest副本。要检查这一点,可以在构造函数中输入print:

class CTest {
public:
  CTest() {
    cout << "Constructor called";
  }    
...
};

如果随后调用程序,将看到构造函数只被调用一次。

当调用isitme时,将this指针与cobj参数的地址进行比较。它们都指向同一个对象,所以它们都包含相同的内存地址。因此,比较通过。

另一件要注意的事情是你是通过引用传递的。如果你没有通过引用传递,那么这将不起作用。例如,如果您有以下代码:

class CTest {
public:
...
  bool isitme(CTest cobj) {
    return this == &cobj;
  }
};

则对象将按值传递。结果,生成了cobj的副本。实际上,调用另一个构造函数(编译器提供的默认复制构造函数)来创建一个新对象,该对象是给定对象的副本。

要证明这一点,覆盖默认复制构造函数以显示消息。

class CTest {
public:
  // Default constructor
  CTest() {
    cout << "Constructor called" << endl;
  }
  // Copy constructor
  CTest(CTest& source) {
    cout << "Copy constructor called" << endl;
  }
  // Comparison
  bool isitme(CTest obj) {
    return (this == &obj);
  }
};
// Main program
int main (int argc, char* argv[]) {
  ...
  CTest a;
  CTest* b = &a;
  cout << (b->isitme(a)) << endl;
  ...
}

现在如果你运行这个程序,你会注意到两个构造函数都被调用了。第一次是在a的构造函数期间。第二次是当您将a传递给isitme方法时,它会创建一个副本。

当按值传递时,isitme检查将失败,因为它比较的是两个不同对象的指针(内存地址)

int CTest::isitme(CTest &cobj) 
{ 
    // cobj is a reference, but still an object
    CTest * pCobj = &cobj; //pCobj is now the pointer to the actual memory
    //so it's the same as this pointer. Because you did before CTest *b = &a;        
}

b指向a,则在

中使用a
b->isitme(a)

isitme()只是根据this检查作为参数传递的对象。在本例中是OK