Other C++ tidbits

Recently there have been posts about C++ on Planet KDE, so I just thought I’d chip in.

Someone was wondering why a class must define operator=() even though a perfectly good copy ctor already exists. Personally I think that the compiler should automatically define a operator=() somehow based on the copy ctor. I’m willing to bet that the reason this isn’t done is because that by declaring a default ctor or copy ctor manually, you have pointed out to the compiler that there is something special that needs to be done which isn’t done by default, and this is probably true for the assignment operator as well.

Ruurd mentioned how important it is to implement the Big Four for C++ classes, which are the constructor, copy constructor, assignment operator, and destructor. He’s right, but if you’re like me and don’t feel like typing it in manually, you should know that if you leave the constructors and assignment operator undefined, then C++ will define them for you. The compiler-generated functions will merely copy the data members over. One thing to note is that although basic data types like pointers, int, bool etc will just be copied byte-for-byte, any class data members will be copied by having their copy constructor or assignment operator called as appropriate. This means that you can use QString data members and such without being forced to define the initializers as long as the default behavior is appropriate. Note: If you’re holding a pointer the default behavior is probably never appropriate.

A final point is that Ruurd noticed that Foo a = b acts weird. Or in other words, code that does this:

void func(const Foo &b) {
  Foo a = b;
}

Would actually call Foo::Foo(const Foo &other), not Foo::Foo() followed by Foo::operator=(const Foo &other) as some would expect. This is a flaw in the language design since based on the behavior of new, I would expect that Foo a with no parameters would implicitly call the default ctor since Foo *pFoo = new Foo does that. (In fact, that syntax is required, new Foo() doesn’t work, and neither does Foo a();).

But consider the alternative. The new object is going to be created for the first time in the Foo a = b line. Most of the time you’re not trying to call the default ctor followed by the assignment operator, you just want to duplicate b. So in this case, C++ does what you meant (which is refreshing, for once). It’s also normally an optimization. Imagine having to have a coding standard to always use the relatively weird looking Foo a(b) syntax to duplicate an object instead of having the compiler figure it out for you. I wouldn’t want that, and besides, I can’t think of too many situations where it would be a good idea for:

Foo a; a = b;

to mean something different from:

Foo a(b);