Reputation: 4579
Assume there is a need to implement getters/setters (also I try to avoid them whenever possible because they often indicate bad design). Which variant of the following two is better and what are the implications of each?
Possibility (1):
class Foo;
class Bar
{
public:
const Foo& getFoo() const {return foo_;}
private:
Foo foo_;
};
or (2):
class Foo;
class Bar
{
public:
void getFoo(Foo& foo) const {foo = foo_}
private:
Foo foo_;
};
Personally, I use always the first variant, because I find it more intuitive. In the second variant you have to construct the Foo object, which will hold the result of getFoo, before calling getFoo and then pass getFoo a reference to this object. This variant feels counterintuitive to me, but there are people, who prefer the secodn variant. For what reason might be the second variant superior to the first one?
Upvotes: 0
Views: 671
Reputation: 76376
Output arguments should be considered criminal offence. It's more difficult to use, but especially much more difficult to maintain, because it's just not visible in the code. If something is assigned to, it's clear. If a method is invoked on object, it's kind of expected it might modify it. But if it's only passed to a function, normal maintenance programmer won't suspect it's being modified. Plus most of the time it requires extra line for declaring a temporary variable to accept the value.
This kind of thing is mainly written by people who stopped at C89 and somehow learned C++ syntax. But with C++ copy elision and move semantics of C++11 I don't see any valid reason worth making the code more difficult to read.
Of course if you are returning a member, you can return const reference to it. If the value is computed, just return by value and copy elision will take care of it most of the time.
Upvotes: 7
Reputation: 9089
First variant is of course preferable in general case. Due to Return Value Optimization (RVO) it is not less effective than second as returned object is not copied and there is no performance overhead.
Second variant could be preferable if you need to have some preliminary setup on passed object or use some partial copy. But this is not trivial getter anymore, of course, but some different function with different semantics.
Another possible reason to use second variant - when passed object could not be created directly by the holding class, e.g. its creation is encapsulated by some factory and you don't want to make your class dependent on this factory.
Upvotes: 0