【发布时间】:2020-12-02 13:47:06
【问题描述】:
我想问一个关于复制引用运算符的问题。
我有一个名为 Mystring 的类,并且我有一个复制引用运算符,它可以工作。
#ifndef _MY_STRING_
#define _MY_STRING_
class Mystring
{
private:
char *str; // pointer to a char[] that holds a c-style string
public:
Mystring(); // no args
Mystring(const char *s); // overloaded
Mystring(const Mystring &source); // copy
~Mystring(); // destructor
Mystring &operator=(const Mystring &rhs);// overloaded copy assignment operator
void display() const; // getters
int get_length() const;
const char *get_str() const; // pointer is returned
};
#endif // _MY_STRING_
这是复制引用运算符函数:
// Overloaded assignment copy operator
Mystring &Mystring::operator = (const Mystring &rhs) {
std::cout << "Copy assignment" << std::endl;
if (this == &rhs) // check the pointer is on the same address of rhs i.e. & = reference operator
return *this; // returns the reference
delete [] this->str;
str = new char [std::strlen(rhs.str) + 1];
std::strcpy(this->str, rhs.str);
return *this;
}
我是 C++ 的初学者,所以这很令人困惑,但我会尝试描述会发生什么。
我知道有一个this 运算符,它充当指针。当取消引用时,它允许我们使用对象本身。
从第一行开始
Mystring &Mystring::operator = (const Mystring &rhs)
我可以看到我将有一个返回引用的运算符函数,因为 & 运算符存在于声明中。
但是,在 if 语句和整个函数的末尾,我们声明
return *this
虽然如果我们取消引用 this,我们将返回对象而不是根据我上面的解释的引用。
Microsoft c++ 文档还指出
表达式
*this通常用于从成员函数返回当前对象:
为了澄清,this 是一个指向当前对象的指针,所以*this 然后返回它应该意味着我正在返回对象,而不是另一个引用。
我在理解这段代码时犯了什么错误?
【问题讨论】:
-
#define _MY_STRING_该标识符保留给语言实现。通过定义它,您的程序将具有未定义的行为。您应该使用另一个标头保护。 -
*this和所有命名变量都可以绑定到引用,因为它们是对其对象的左值(~命名)引用。&也有多种含义——一个是变量的地址,另一个是引用类型,它们并不完全相同。所以int& var和*ptr不是相反的操作。int var; int*ptr =&var和*ptr将是。 -
@Quimby 我理解,但我的困惑是
return *this暗示将返回对象本身,但是代码似乎通过声明将返回对当前对象的引用来工作,并且我不明白这是怎么回事。this是指向当前对象的指针,所以*this然后返回它应该意味着我正在返回对象,而不是另一个引用。我希望这能让我的原意更清楚。 -
@bodn19888 是的,它归结为表达式的value categories,这不是一个真正适合初学者的话题。但是
*this本身就是一个命名引用。这就是为什么您的字符串复制构造函数可以执行std::string str; Mystring s(str)之类的操作。这里str也必须参考。它必须,首先您将如何分配给引用。没有str的副本,只是参考。这完全一样,但是对象的名称是*this,它也可以绑定到一个引用。 -
int var;,var表示我是我存储的对象的名称。int& r = var意味着r将只是同一对象的另一个名称。int var2 = var的意思是:我将复制var所引用的对象,并将为这个新对象重新命名。*this也只是一个名字,不用担心this是一个指针。您可以使用Mystring s = *this并复制一份名为s的副本。或者您可以执行Mystring& r = *this并且会发生与int&完全相同的事情,r将引用与*this相同的对象,即为该对象指定一个新名称。