3

I was reading through some c++ source code, and i came over some syntax.

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

and i was wondering whether it is actual syntax and why c++ is not using the already existing operator+ instead combined with applying the value to the object in question.

Is it like, if you want to make sure that the object gets deleted properly. But the destructor should deal with all of that.

-Edit1

I know there is a difference between a += b; and a + b;
What i was wondering was why does c++ not just use the operator+ with the += instead of having to redefine the operator+= as the same as the operator+

-Edit2

Im not sure it came across correctly, but what i was asking was why the language doesn't infer += based on +. And now i realize the other uses of +=. Thanks everyone :)

vsoftco
  • 55,410
  • 12
  • 139
  • 252
drpytho
  • 125
  • 2
  • 10
  • 5
    there is a difference between writing `a += b;` and `a + b`. Mainly in that the first expression modifies a, whereas the second will not – Creris Feb 05 '15 at 12:28
  • BTW, also `operator+=` already exists. – Antonio Feb 05 '15 at 12:29
  • 2
    The expressions `a += b` and `a = a + b` are not equal. In the first case (`a += b`) the expression `a` will be evaluated only once, but in `a = a + b` it will be evaluated twice. Think about if the expression `a` is actually an expression and not a variable, and if that expression have some side-effect. – Some programmer dude Feb 05 '15 at 12:32
  • @Creris OP knows that. He is asking why the language doesn't infer `+=` based on `+`. –  Feb 05 '15 at 12:41
  • @рытфолд Yes, exactly. Thank you :) I was not sure it came across correctly. – drpytho Feb 05 '15 at 13:00

5 Answers5

9
  1. There may be efficiency concerns; if your object is expensive to copy/assign, a+=b potentially saves you a temporary construction, a copy construction and an assignment, and allow you to better exploit the resources you already have in a target object. If std::vector had a += operator to concatenate vectors, it would be way more efficient to implement it directly (you can exploit the extra capacity of the target object and avoid useless allocations) instead of creating a temporary sum vector (which starts "from scratch") and assigning it.

    Actually, normally I implement + in terms of +=, usually it yields code that is both more efficient and easier to write; like this:

    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;
    }
    

    (although I agree that it would be nice to have a way to ask the compiler to synthesize the +/- from the existing operators; the same for the relational operators)

  2. You may want to have an object that can be added something but cannot be copied/assigned. For example, for a toy project of mine I briefly considered having signal objects (think boost or Qt, or .NET events/multicast delegates) that overloaded += to add a connection (Signal &operator+=(std::function<T...> fn)), but I didn't want to deal with the assignment/copy semantic (that IMHO for a signal doesn't make sense);

  3. At the bottom of it all, there's the general idea that in C++ you can overload (almost) all operators to have them do whatever you want, without particular restrictions of semantics. You can write an operator+ that launches a rocket and an operator+= that deletes all the files on your hard disk - you are in charge, if it makes sense in your application you are free to do it without particular restrictions.

Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
  • is it more readable to write opeartor+ like this? T operator+(const T &r){ return T{*this} += r; } – User8500049 Jan 28 '19 at 11:33
  • You should avoid explicitly call the copy constructor by passing the parameter of operator+ by value, as `T operator+(T)` – R. Absil Nov 18 '22 at 06:44
  • @R.Absil with members functions that's possible only for commutative operations, unfortunately. In this case it would be ok (I could do `r += (*this); return r;`), but that would not work for e.g. a `+=` / `+` for `std::vector`. To make it work correctly for a non-commutative operation exploiting the construction done in the argument (which can make sense essentially to exploit rvalues and move construction) one has to make the operator a free function. I'll add these remarks in the answer when I have some time. – Matteo Italia Nov 18 '22 at 13:54
6

C++ makes no assumptions with regards to overloaded operators; you can define an operator+ which is not commutative, for example. And you can define an operator+= which has no relation to the operator+. You can also define an operator+= without defining operator+ or vice versa.

As to why: for starters, you really wouldn't want the compiler to assume that operator+ on strings is commutative, and optimize in consequence. And once having opened the door, the authors of the language no doubt felt that it was best to leave it up to the programmer, rather than to impose anything at language level. Even if I can't think of a case off-hand, there may be cases where it makes sense to support += and + with slightly different semantics. The general philosophy of C++ has always been to give the programmer all of the tools he requires to write good code, but not to ban code which isn't conform to the current idea of what is bad code. (In the long run, this has paid off, since our ideas as to what is good and bad code have evolved.)

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • 1
    And anyway, it would make more sense to automatically synthesize `+` from `+=` and copy-ctor, than the other way around. – Deduplicator Feb 05 '15 at 12:45
  • @Deduplicator Often. Probably even usually. But not always. (When designing numeric types, of course, the usual procedure is to define only the op= operators, and to derive from an `ArithmeticOperator` class template which defined the `+` in terms of `+=`. But that's just a common pattern, and there are cases where it makes a lot of sense to provide separate implementations.) – James Kanze Feb 05 '15 at 12:52
  • Well, while I think using different *semantics* there is simply inexcusable, think about a set-addition-operator: If you define `+` using `+=`, you (probably) need to re-allocate. If you don't, you could be done with a single allocation. – Deduplicator Feb 05 '15 at 13:05
  • 1
    @Deduplicator While I can't think of a case where you'd define both `+` and `+=` with unrelated semantics (in reasonable code, at least), I can imagine cases where you might define `+=` without defining either `=` or `+`. – James Kanze Feb 05 '15 at 13:12
  • Yeah what might be good code today may inadvertently be bad code in 5 years from now... However what ever is bad today will probably still be bad in 5 years... – Francis Cugler Nov 07 '18 at 14:01
1

Yes, path& path::operator+=(string postPath); is valid and overloads the += operator for the case in which a string is added onto a path.

The reason why you want to be able to overload it is simple: operator+ must return a new value instead of changing the old one, while operator+= can reuse existing resource (e.g. allocated memory). Since the major operation of appending strings (which is what you are doing) is memory allocation, a += can be significantly more performant in your exact case.

Additionally, the operation SomePath + SomeString raises the question of SomeString + SomePath, and even worse, SomeStringA + SomePathB, all of which are slightly different, while SomePath += SomeString has a very clear meaning.

Since it shoud now be clear why you want to be able to implement += without implementing +, consider the other direction: Why not just use a = a + b as the default implementation for a += b:

First, the operator overloading rules are older than = delete. Therefore, this rule would always trigger, even in cases where you do not want operator+= to exist at all. Note that implementing the "default" is very simple:

A& operator+=(A const& other) { return *this = *this + other; }
danielschemmel
  • 10,885
  • 1
  • 36
  • 58
0

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

Precisely because the += mutates, and + doesn't. That often implies significant differences in the implementation.

Bartek Banachewicz
  • 38,596
  • 7
  • 91
  • 135
0

Implementing a += b as a = a+b would be less efficient than implementing it directly, since it would have to create and destroy the temporary object that's assigned to a.

It's more efficient to implement + in terms of +=

path operator+(path prePath, string postPath) {
    return prePath += postPath;
}

Philosophically, one might argue that it's less surprising if the language doesn't magically generate operators that you might not expect. Many people are caught out by implicitly-generated constructors and assignment operators giving their types invalid copy semantics (until they learn the Rule of Three), and other magical behaviour might cause confusion in other ways.

Community
  • 1
  • 1
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • I totally agree with your last paragraph. But it does raise a question: why not support `operator+() = default` or something along those lines? – James Kanze Feb 05 '15 at 12:53
  • @JamesKanze: As long as there's agreement on what the "default" should be, then why not indeed? Making it easy to generate things you want is a fine idea; generating things you didn't ask for, and might not want, not so much. – Mike Seymour Feb 05 '15 at 12:59
  • I agree. Maybe I should find the time and write up a proposal. (IMHO, the "default" `operator+` should be a free function.) On the other hand, it's very easy to get all of the operators you want just be deriving from an `ArithmeticOperators` class; maybe I should propose that instead. – James Kanze Feb 05 '15 at 13:08