【问题标题】:overloading copy assignment operator with classes without a reference parameter name使用没有引用参数名称的类重载复制赋值运算符
【发布时间】:2020-08-15 14:03:51
【问题描述】:

我想问一个关于 C++ 中运算符重载的问题。

我是 C++ 初学者,一直在学习 OOP。

考虑以下重载的复制赋值运算符:

class Base {
private:
    int value;
public:
    Base () : value {0} 
    {
        cout << "Base No-args constructor" << endl; 
    }
    Base (int x) : value {x} {
        cout << "Base (int) overloaded constructor" << endl;
    }
    Base (const Base &other) : value {other.value} {
        cout << "Base copy constructor" << endl;
    }
    Base & operator = (const Base &rhs) {
        cout << "Base operator=" << endl;
        if (this == &rhs)
            return *this;
        value = rhs.value;
        return *this;
    }

    ~ Base () {cout << "Base Destructor" << endl;}
};

我想澄清两点。

  1. 这个复制赋值运算符是如何工作的?
  2. operator关键字前的引用是否需要参数名?

我想就 (1) 给出我的解释。

如果我的main() 中有以下代码:

Base b {100}; // overloaded constructor
Base b1 {b}; // copy constructor
b = b1; // copy assignment

我认为发生的情况是a1 调用了无参数构造函数,显然是因为没有参数传递到对象的构造中。 当a2 被初始化时,会生成a1 的临时副本,然后根据Base 类评估运算符,因此运行Base 重载复制分配块,并且a1 对象是通过return *this 返回到引用a2

为了解释我对第二个问题的想法,

我认为声明函数或方法时所有参数都需要一个名称(我当然可能错了)。

如果我的重载复制分配块假设写为:

Base &lhs operator = (const Base &rhs)

我说lhs 指的是a2 是否正确,但是由于隐含的this 参数,我们不对lhs 做任何事情,我们不需要在后面给出参数名称运算符前面的 & 号?

【问题讨论】:

  • Base a2 = a1; 是通过复制构造函数初始化a2。它不使用赋值运算符。
  • @Eljay 我更新了代码以更好地适应问题!

标签: c++ operator-overloading


【解决方案1】:

这个复制赋值运算符是如何工作的?

已编辑:

Base& operator=(Base const& rhs) {
    cout << "Base operator=\n";
    value = rhs.value;
    return *this;
}

赋值运算符只是一个函数调用。在这个特定的类的例子中,编译器会合成一个做正确的事,但是如果你想要 cout 的副作用用于教育目的,你做对了。

你也可以用方法函数风格调用它:

b.operator=(b1);

b = b1; 只是上面的语法糖。

赋值运算符应该是自赋值安全的。但一般指导是在不明确检查自分配情况的情况下使其安全,这是“不好的”,因为它针对病态情况进行了优化。

在您的实现中,没有自分配检查是安全的。

我更喜欢以Base const&amp; 顺序而不是const Base&amp; 顺序指定限定符,因为一般规则是“限定符总是绑定到紧靠其左侧的事物”,一般规则的例外是“.. . 除非限定符先出现,在这种情况下,它会绑定到其直接右侧的事物。”当人们掌握了规则的例外而不是一般规则,然后在他们的头脑中解析Base*const*时遇到了麻烦。

operator关键字前的引用是否需要参数名?

它的名字是*this。是返回类型,不是参数,所以没有参数名。

有些人对“为什么 C++ 使用 this 作为指向自身的指针,而不是作为对自身的引用”感到困扰。

这是 C++ 发展过程中的一个历史反常现象。最初,有一个this 指针,还没有在语言中添加引用。

事后看来,this 本来可以作为参考。但是那艘船已经航行了。

在我自己的代码中,只是为了让它更清晰,我会这样做:

auto& self = *this;
self[i] = 5;

...而不是更令人困惑的(imo)...

(*this)[i] = 5;

【讨论】:

  • 当你说“它的名字是*this。它是一个返回类型”时,如果我没记错的话,&amp; 表示返回类型是一个l-value 类型即它在内存中有一个位置,这是我们返回的对象*this?我最初的想法是通过将&amp;表示为返回类型,这意味着返回类型是一个引用,但我们是通过return *this返回对象本身,对吧?
  • @bodn19888 • 正确,它返回一个引用 到自身,它允许链接b = b1 = b2; 我不喜欢链接,但void operator=(Base const&amp;) 不会是惯用的C++,这会让我的同事脾气暴躁。所以我遵循惯用的约定。
  • 哦,对了,我刚刚检查了 cpp 引用,他们说 关键字this 是一个prvalue 表达式,其值是隐式对象参数的地址 所以用莱曼的话this 只是一个指向对象本身引用的指针?对于初学者来说,God C++ 有时会非常困难。
  • 请注意,在 C++ 中,引用是 alias ...同一对象的另一个名称;其他语言(如 Java 或 C#)在不同的意义上使用术语“引用”。 C++ 确实有一个相当艰巨的学习曲线,我建议向其中一个 good C++ books 学习。
  • ahhhhhhhh @Eljay 在返回中使用thisthis 本身就是对对象的引用,因为它是一个别名。是的,现在我明白了,谢谢!
猜你喜欢
  • 1970-01-01
  • 2011-06-13
  • 2013-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-12
  • 1970-01-01
  • 2017-07-09
相关资源
最近更新 更多