运算符重载,operator+ vs operator+=

Operator overloading, operator+ vs operator+=

我正在阅读一些 C++ 源代码,并且了解了一些语法。

path& path::operator+=(string postPath)

我想知道这是否是实际语法,以及为什么 C++ 不使用已经存在的运算符+,而是结合将值应用于相关对象。

是不是,如果你想确保对象被正确删除。但是析构函数应该处理所有这些。

-编辑1

我知道a += b是有区别的;和 a + b;
我想知道的是,为什么 C++ 不只是将 operator+ 与 += 一起使用,而不必将 operator+= 重新定义为与 operator+

相同

-编辑2

我不确定它是否正确,但我想问的是为什么该语言不根据 + 推断 +=。 现在我意识到 += 的其他用途。谢谢大家:)

C++ 没有 关于重载运算符的假设;你可以 例如,定义一个不可交换的 operator+。和你 可以定义一个与 operator+ 无关的 operator+=。 您还可以定义一个 operator+= 而不定义 operator+ 或副 相反。

至于原因:对于初学者来说,您真的不希望编译器假设 字符串上的 operator+ 是可交换的,因此会进行优化。 一旦打开门,语言的作者无疑 觉得最好把它留给程序员,而不是 在语言层面强加任何东西。就算想不出案例 副手,在某些情况下支持 +=+ 语义略有不同。 C++的一般哲学 一直是给程序员他需要的所有工具 写好代码,但不禁止不符合现行的代码 什么是坏代码的想法。 (在很长的 运行 中,这已经得到回报,因为 我们关于什么是好代码和坏代码的想法已经演变。)

why c++ is not using the already existing operator+ instead combined with applying the value

正是因为 += 变异了,而 + 没有。这通常意味着实施中存在重大差异。

是的,path& path::operator+=(string postPath); 是有效的,并且在将 string 添加到 path 的情况下重载了 += 运算符。

你想要重载它的原因很简单:operator+ 必须 return 一个新值而不是改变旧值,而 operator+= 可以重用现有资源(例如分配的内存)。由于附加字符串的主要操作(这是您正在做的)是内存分配,因此 += 在您的具体情况下可以显着提高性能。

此外,操作SomePath + SomeString引发了SomeString + SomePath的问题,更糟糕的是,SomeStringA + SomePathB,所有这些都略有不同,而SomePath += SomeString有一个非常意思清楚。

既然现在应该清楚为什么您 想要 能够实现 += 而无需实现 +,请考虑另一个方向:为什么不只是使用 a = a + b 作为 a += b:

的默认实现

首先,运算符重载规则早于 = delete。因此,即使在您 想要 operator+= 存在的情况下,这条规则也会 always 触发。请注意,实现 "default" 非常简单:

A& operator+=(A const& other) { return *this = *this + other; }
  1. 可能存在效率问题;如果您的对象对 copy/assign 来说是昂贵的,a+=b 可能会为您节省临时构造、复制构造和赋值,并允许您更好地利用目标对象中已有的资源。如果 std::vector 有一个 += 运算符来连接向量,直接实现它会更有效(您可以利用目标对象的额外容量并避免无用的分配)而不是创建一个临时总和向量(从 "from scratch" 开始)并赋值。

    实际上,我通常根据 += 来实现 +,通常它会产生更高效且更易于编写的代码;像这样:

    T &operator+=(const T &r)
    {
        // say that T encapsulates an N-dimensional array
        for(int i=0; i<N; ++i)
            arr+=r.arr[i];
        return *this;
    }
    
    T operator+(const T &r)
    {
        T ret(*this);
        ret+=r;
        return ret;
    }
    

    (尽管我同意有一种方法可以让编译器从现有运算符中合成 +/- 会很好;关系运算符也是如此)

  2. 你可能想要一个可以加东西但不能加东西的对象copied/assigned。例如,对于我的一个玩具项目,我简单地考虑过让信号对象(想想 boost 或 Qt,或 .NET events/multicast 委托)超载 += 以添加连接(Signal &operator+=(std::function<T...> fn)),但我不想处理 assignment/copy 语义(恕我直言,信号没有意义);

  3. 归根结底,有一个普遍的想法,即在 C++ 中,您可以重载(几乎)所有运算符,让它们做任何您想做的事情,而没有特别的语义限制。您可以编写一个 operator+ 来发射火箭和一个 operator+= 来删除您硬盘上的所有文件 - 您是负责人,如果它在您的应用程序中有意义,您可以随意执行它而无需特别说明限制。

a += b 实现为 a = a+b 的效率低于直接实现它,因为它必须创建和销毁分配给 a.[=17= 的临时对象]

根据+=

实施+效率更高
path operator+(path prePath, string postPath) {
    return prePath += postPath;
}

从哲学上讲,有人可能会争辩说,如果该语言不会神奇地生成您可能意想不到的运算符,也就不足为奇了。许多人被隐式生成的构造函数和赋值运算符给他们的类型赋予了无效的复制语义所困扰(直到他们学习 Rule of Three),并且其他神奇的行为可能会以其他方式引起混淆。