Reputation: 263310
Suppose I have a class Foo
with a std::string
member str
. What should get_str
return?
std::string Foo::get_str() const
{
return str;
}
or
const std::string& Foo::get_str() const
{
return str;
}
What is more idiomatic in C++?
Upvotes: 20
Views: 9887
Reputation: 114805
In general (unless there's a proven performance issue) I would return by value.
First of all there's a semantic difference, if your property changes do you want your clients to be updated of the change or get the value at the moment of calling the function?
There's the obvious correctness issue, if you return by reference the entity calling the function may hold on to the reference and may use it after your object was destructed (which is not so good).
Another problem is with multiple threaded code, if one thread reads from the const reference while you're updating the variable you're in for lots of trouble.
In any case I think the most common use case is when the caller of the function stores the value in a variable.
string val = obj->get_str();
// use val now
If this is true (as opposed to cout << obj->get_str()
where there is no variable) you always have to construct a new string for val
even if you return by reference and since compilers can perform RVO the by-value version will not under-perform the by-const-ref variant.
In conclusion: if you know it's a performance issue and you are sure that the return value will not be stored for longer than your object will exist and you don't expect to be used from different threads, then it's OK to return by const reference.
Upvotes: 6
Reputation: 792837
One of the goals of having an accessor method is to try, at least to some extent, to abstract your class implementation from its interface.
Returning by value is better because there are no lifetime issues with the referenced object. Should you decide not to have a std::string
member but, say, a std::stringstream
or to create a std::string
on the fly you don't have to change the interface.
Returning by const
reference isn't the opposite of taking a parameter by const reference, taking a value by const
reference doesn't tie your internal data representation to the external interface.
Upvotes: 7
Reputation: 116306
The short answer is: it depends :-)
From the performance point of view returning a reference is (usually) better: you save the creation of a new std::string
object. (In this case, the creation is costly enough and the size of the object is high enough to justify make this choice at least worth considering - but this is not always the case. With a smaller or built-in type the performance difference may be negligible, or returning by value may even be cheaper).
From the security point of view returning a copy of the original value may be better, as constness can be cast away by malicious clients. This is especially to be taken into consideration if the method is part of a public API, i.e. you(r team) have no full control over how the returned value is (mis)used.
Upvotes: 18
Reputation: 31445
Returning by value means you do not have to have an internal std::string stored somewhere in the class for which you return.
In a pure virtual method it is preferable not to assume that the std::string will be there and therefore to return a std::string by value.
In a concrete class where there is clearly a std::string member and you are just going to return a reference to it, you can, for efficiency, return it by const reference. Even if you have to change it later, you do not need to change functionality that uses the class.
In a multi-threaded model where the inner string might change between calls, of course, you probably need to return by value (assuming that users of the class will get a "snapshot" view of the string value at the time of the completion of the call).
Returning by reference is usually more efficient. I do however have a non-mutable reference-counted string class that you can return by value efficiently and I used to use that quite frequently.
By the way, some would recommend returning a std::string by const value. I do not think it is the best way to do it, as it prevents allowing the user to "swap" it into a local variable.
Upvotes: 2
Reputation: 38820
Generally you should return PODs by value (e.g, int, short, char, long etc,) and a const reference for more complex types:
int getData() const;
short getMoreData() const;
const std::string& getName() const;
const ComplexObject& getComplexData() const;
Upvotes: 1
Reputation: 361692
It depends on what you want to do with the return value.
This is better if you just want to make a query and not modify str
.
const std::string& Foo::get_str() const
{
return str;
}
Otherwise, go for this:
std::string& Foo::get_str()
{
return str;
}
And if you want a copy/clone of str
, then use this:
std::string Foo::get_str() const
{
return str;
}
Upvotes: -1
Reputation: 122429
I believe the second implementation (const reference) is correct as:
str
.However the first approach will work almost as well.
Upvotes: 0
Reputation: 73493
AFAIK, the rule is same as the one which is used while deciding whether to take a function parameter by value or const reference. If the sizeof
the value being returned is small enough then I tend to use returning a copy else return a const reference.
Upvotes: 1