7

In C++, is A+=B preferable to A=A+B in the same way ++A is to A++?

I understand that a "++A" preincrement is guaranteed to be at least as fast as a "A++" postincrement. This is discussed many places including here and here. Likewise, A+=B is expected to be at least as fast as A=A+B, as here.

I was looking at this for ++:

//From https://herbsutter.com/2013/05/13/gotw-2-solution-temporary-objects/
T T::operator++(int)() {
auto old = *this; // remember our original value
++*this;          // always implement postincr in terms of preincr
return old;       // return our original value
}

My reasoning is that in the worst case (probably from complex object types) A=A+B would have to retrieve and store A and add in B before saving it back to the original A location, while A+=B would take B and add it to A directly. Is my reasoning correct?

It is expected that basic types are rearranged as the same at compile time, and that this really only applies to complex objects requiring operator overloading.

Does this extend generically to most imperative languages?

Community
  • 1
  • 1
MathFromScratch
  • 133
  • 1
  • 5
  • `a++` is preferable on some architectures. – user207421 Jun 11 '16 at 21:30
  • 2
    If you are concerned about this level of optimization, maybe you shouldn't be using a high-level language... – Scott Hunter Jun 11 '16 at 21:32
  • 1
    Re: "Does this extend generically to most imperative languages?": C++ is unusual for even having a language-level concept of value assignment for non-primitive types; so the question doesn't even make sense in the context of most other languages. (Of course, a programmer might define `setData` and `plus` and `add` such that `a.add(b)` is equivalent to `a.setData(a.plus(b))`, but at that point you should really be looking at the documentation for the `A` class, rather than trying to reason from general principles.) – ruakh Jun 11 '16 at 21:39
  • 2
    "... a "++A" preincrement is guaranteed to be at least as fast as a "A++" postincrement." This is certainly false. There is no such guarantee. On most architectures and compiler implementations, it is _unlikely_ that preincrement would slower, especially for objects that overload these operators, but it is certainly possible. For primitives it is likely a wash unless your compiler is bad. – BeeOnRope Jun 11 '16 at 22:20
  • 3
    When will people realise that C++ is an abstraction. All this penicketing about "performance" on such low-level operations is, by definition, pointless. – Lightness Races in Orbit Jun 11 '16 at 22:24
  • Voting to close as primarily opinion based. – Carey Gregory Jun 11 '16 at 22:31

5 Answers5

6

I would say the reasons aren't quite the same. My main reason for prefering A += B over A = A + B is conciseness. A += B clearly states that you want to add B to A. This is especially true if A is a more complex expression:

node_capacities[std::make_pair(node1,node2)] += edge.capacity;

I've never found the performance of A += B to be worse than A = A + B either.

Vaughn Cato
  • 63,448
  • 5
  • 82
  • 132
4

The big thing to remember is that C++ have operator overloading which means that te += operator can mean something completely different from what you expect.

The += operator only works as add and assign to if the "destination" class doesn't have an += operator defined for it. Operator overloading also means that e.g x++ can mean different thing depending on what the class instance of x defines for operator overloads.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 1
    *"The += operator only works as add and assign to if the "destination" class doesn't have an += operator defined for it."* -- Huh? If the destination class doesn't have `operator+=` defined for it, then `+=` doesn't work on it at all. – Benjamin Lindley Jun 11 '16 at 21:43
  • 2
    This is true (or will be once you've addressed Benjamin Lindley's comment), but I don't think it really answers the question. It's good to be aware that some C++ code is terrible, so that you know to look at the code before deciding whether to allow it into your project; but the OP is obviously more interested in the best way to use non-terrible code that is already allowed into the project. (And FWIW, the OP is obviously already aware of operator overloading, since (s)he mentions it by name, and gives an example of implementing `x++` in terms of `++x`.) – ruakh Jun 11 '16 at 21:48
  • 1
    Not sure this adds much. In C++, every single line of code _can mean something completely different from what you expect_. Nobody should overload operators for 'interesting' purposes without written permission from five separate deities. – Roddy Jun 11 '16 at 22:32
3

You should prefer A += B;.

If you ever wrote a type where A = A + B; turned out to be better than A += B;, then you should change the implementation of operator+= to do exactly what A = A + B; does.

However, the reverse generally can't be done; you usually can't modify operator+ in any reasonable fashion to make A = A + B; do exactly the same thing as A += B;.

Thus, if there is a difference between A += B; and A = A + B;, you should expect A += B; to be the better choice.

  • Ahh, ok. that's a good point - because the A=A+B would be a ternary user defined operator. I am reading through [the c++11 draft spec n3242.pdf](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf) and [this question about it](http://stackoverflow.com/questions/17953437/c-why-is-it-not-possible-to-overload-the-ternary-operator) and there doesn't seem to be those. – MathFromScratch Jun 13 '16 at 15:44
1

In most cases, A+=B is preferable. As you have pointed out, there would be more register loads in A = A + B vs A+=B. Also of interest might be to read up on SSA. This is used in compiler optimization, and might help understand how such case is dealt with. As you have said, most of these considerations are taken out of the programmers hands thanks to the compiler, but it is good to be aware of these things.

Another consideration to account for in complex objects is the possible side effects caused by calling getters, and the fallout for calling such getter twice. (Think, A.get() = A.get() + B.get()). This however should be relatively rare, since getters should not have side effects in most cases.

  • In your "A.get() = A.get() + B.get()", type A's get() method would be returning an address? If not, why wouldn't it then have to be "A.set(A.get()+B.get())"? – MathFromScratch Jun 13 '16 at 15:05
-3

In fact, in C++ you should avoid postfixed operators:

  • ++a //here the operator ++ is prefixed
  • a++ //here the operator ++ is postfixed

Just because the postfixed solution will use the value of a then increase its value, which can be dangerous some times, or at least decrease some performances.

You can take a look here for further informations.