Depends on what you mean by real work. The constructor should put the object into a usable state, even if that state is a flag meaning it hasn't yet been initialised :-)
The only rationale I've ever come across for not doing real work would be the fact that the only way a constructor can fail is with an exception (and the destructor won't be called in that case). There is no opportunity to return a nice error code.
The question you have to ask yourself is:
Is the object usable without calling the init
method?
If the answer to that is "No", I would be doing all that work in the constructor. Otherwise you'll have to catch the situation when a user has instantiated but not yet initialised and return some sort of error.
Of course, if you can re-initialise the device, you should provide some sort of init
method but, in that case, I would still call that method from the constructor if the condition above is met.