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

时间:2015-02-05 12:27:04

标签: c++ overloading

我正在阅读一些c ++源代码,我找到了一些语法。

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

我想知道它是否是实际语法以及为什么c ++没有使用已经存在的运算符+而是将值应用于相关对象。

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

-Edit1

我知道a + = b之间存在差异;和a + b;
我想知道为什么c ++不仅仅使用运算符+ + +而不必重新定义运算符+ =与运算符+

相同

-Edit2

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

5 个答案:

答案 0 :(得分:6)

C ++对重载运算符进行 no 假设;您可以 例如,定义一个不可交换的operator+。你呢 可以定义与operator+=无关的operator+。 您还可以定义operator+=而无需定义operator+或副词 反之亦然。

至于为什么:对于初学者,你真的不希望编译器假设 字符串上的operator+是可交换的,并因此进行优化。 一旦打开了门,这种语言的作者毫无疑问 觉得最好把它留给程序员,而不是 在语言层面强加任何东西。即使我无法想到一个案例 另一方面,可能存在支持+=和{}的有意义的情况 +语义略有不同。 C ++的一般哲学 一直以来都为程序员提供了他所需要的所有工具 写好的代码,但不要禁止不符合当前的代码 什么是坏代码的想法。 (从长远来看,这已经得到了回报,因为 我们关于什么是好的和坏的代码的想法已经发展。)

答案 1 :(得分:6)

  1. 可能存在效率问题;如果您的对象复制/分配成本高昂,a+=b可能会为您节省临时构造,复制构造和分配,并允许您更好地利用目标对象中已有的资源。如果std::vector有一个+=运算符来连接向量,那么直接实现它会更有效(你可以利用目标对象的额外容量并避免无用的分配)而不是创建一个临时总和矢量(从头开始"从头开始")并分配它。

    实际上,通常我会在+方面实现+=,通常会产生更高效,更容易编写的代码;像这样:

    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. 您可能希望拥有一个可以添加但无法复制/分配的对象。例如,对于我的玩具项目,我简要地考虑过重载+=以添加连接(Signal &operator+=(std::function<T...> fn))的信号对象(想想boost或Qt,或.NET事件/多播委托),但是我没有想要处理任务/复制语义(恕我直言,信号没有意义);

  3. 最重要的是,在C ++中你可以重载(几乎)所有运算符让它们做任何你想做的事情,而不受语义的特殊限制。您可以编写一个operator+来启动火箭,一个operator+=删除硬盘上的所有文件 - 您负责,如果在您的应用程序中有意义,您可以自由地执行此操作限制。

答案 2 :(得分:1)

是的,path& path::operator+=(string postPath);有效,并且+=运算符会因string添加path的情况而重载。

您希望能够重载它的原因很简单:operator+必须返回新值而不是更改旧值,而operator+=可以重用现有资源(例如分配的内存)。由于追加字符串的主要操作(您正在执行的操作)是内存分配,因此在您的确切情况下,+=可以显着提高性能。

此外,操作SomePath + SomeString提出SomeString + SomePath的问题,更糟糕的是SomeStringA + SomePathB,所有这些都略有不同,而SomePath += SomeString具有非常明确的含义

由于现在很清楚为什么你希望能够在不实施+=的情况下实施+,请考虑另一个方向:为什么不使用{{1} }作为a = a + b的默认实现:

首先,运算符重载规则早于a += b。因此,即使在希望= delete存在的情况下,此规则也会始终触发。请注意,实现“默认”非常简单:

operator+=

答案 3 :(得分:0)

  

为什么c ++没有使用已经存在的运算符+而是结合应用值

正是因为+=发生变异,而+没有变异。这通常意味着实施方面的重大差异。

答案 4 :(得分:0)

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

根据+

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

哲学上,人们可能会争辩说,如果语言没有神奇地产生你可能没想到的运算符,那就不那么令人惊讶了。许多人被隐式生成的构造函数和赋值运算符所捕获,给出了它们的类型无效的复制语义(直到他们学习Rule of Three),而其他魔法行为可能会在其他方面引起混淆。