15

Does the compiler generated assignment operator guard against self assignment?

class T {

   int x;
public:
   T(int X = 0): x(X) {}
};

int main()
{
   T a(1);
   a = a;
}

Do I always need to protect against self-assignment even when the class members aren't of pointer type?

cpx
  • 17,009
  • 20
  • 87
  • 142
  • 1
    No, there's nothing wrong with that. And I don't think there's anything to "guard" against, really. EDIT: Are you talking about a copy-constructor? – Mateen Ulhaq Apr 09 '11 at 23:11
  • 2
    If no class members are pointers/smart types, then the answer is no. No need to protect against it. The behavior is the same as for POD (plain old data) in that case ... – 0xC0000022L Apr 09 '11 at 23:13

3 Answers3

15

Does the compiler generated assignment operator guard against self assignment?

No, it does not. It merely performs a member-wise copy, where each member is copied by its own assignment operator (which may also be programmer-declared or compiler-generated).

Do I always need to protect against self-assignment even when the class members aren't of pointer type?

No, you do not if all of your class's attributes (and therefore theirs) are POD-types.

When writing your own assignment operators you may wish to check for self-assignment if you want to future-proof your class, even if they don't contain any pointers, et cetera. Also consider the copy-and-swap idiom.

Community
  • 1
  • 1
johnsyweb
  • 136,902
  • 23
  • 188
  • 247
  • 1
    Adding, removing, or changing data members requires you to revisit op= (among others) anyway, so an unnecessary self-assignment check gains nothing as far as future-proofing goes. – Fred Nurk Apr 09 '11 at 23:58
  • @Fred Nurk: You're absolutely right. Unfortunately, revisiting `operator =` for new or changed attributes doesn't guarantee the maintainer will Do The Right Thing™. – johnsyweb Apr 10 '11 at 00:08
  • 2
    @Johnsyweb: Adding an unnecessary self-assignment check also doesn't guarantee the maintainer will do the Right Thing, but is more likely to be confusing to someone that does know what they're doing. For example: "unnecessary" is important here, because expensive to copy types which are self-assigned often (rare) would benefit from the check even though it wouldn't be strictly necessary. – Fred Nurk Apr 10 '11 at 01:30
  • 3
    Or restated: a future maintainer will always be able to screw things up, worrying about what they may or may not do isn't productive. Keeping updated, useful docs and writing clear code is all you can do. – Fred Nurk Apr 10 '11 at 01:31
  • 1
    @Fred Nurk: Couldn't agree more. For "updated, useful docs", I read "unit tests" :-) – johnsyweb Apr 10 '11 at 01:38
  • There is no need for checks even if the members are non-PODs, assuming **these** objects have self-assign checks where needed. With the default memberwise assignment, each member is responsible for itself. – Bo Persson Apr 10 '11 at 08:28
  • @Bo: Is that a *safe* assumption? Also consider base classes, as highlighted by [Rob's Answer](http://stackoverflow.com/questions/5608556/assignment-operator-self-assignment/5609167#5609167) – johnsyweb Apr 11 '11 at 09:51
  • 3
    If all members, including base classes, handle their own assignment, there is nothing for you to do. The compiler will generate memberwise copying and assignment by calling each member's operator/constructor in turn. That works fine. Sometimes people belive that the self-assignment test is an optimization, but it can just as well be a pessimisation - adding an extra check to **all** assignments. If self-assignment is extremely common, perhaps we should take a look at the code using the assignment. :-) – Bo Persson Apr 11 '11 at 11:09
5

This is an easy one to check empirically:

#include <iostream>
struct A {
  void operator=(const A& rhs) {
    if(this==&rhs) std::cout << "Self-assigned\n";
  }
};

struct B {
  A a;
};

int main()
{
  B b;
  b = b;
}
Robᵩ
  • 163,533
  • 20
  • 239
  • 308
-2
class T {
    int x;
public:
    T(int X = 0): x(X) {}
// prevent copying
private:
    T& operator=(const T&);
};
Christopher Creutzig
  • 8,656
  • 35
  • 45
xzhai
  • 9
  • 2
  • 1
    It doesn't seem to me cpx wanted to disable the assignment operator. (S)he wanted to use it, but had a question re self-assignment. (Besides, your code had a typo.) – Christopher Creutzig Jun 14 '12 at 08:05