Return smart pointers by value.
As you said, if you return it by reference, you will not correctly increase the reference counter, which opens the risk of deleting something at the wrong time. This in itself should be sufficient reason for refusing the link. Interfaces must be reliable.
Cost concerns are currently troubling due to return value optimization (RVO), so you wonβt follow the increment-increment-decrement sequence or something similar in modern compilers. Therefore, the best way to return shared_ptr is to simply return by value:
shared_ptr<T> Foo() { return shared_ptr<T>(); };
This is a dead-obvious RVO feature for modern C ++ compilers. I know that Visual C ++ compilers implement RVO even when all optimizations are disabled. And with the semantics of C ++ 11 relocation, this problem is even less relevant. (But the only way to be sure is to profile and experiment.)
If you are still not sure, Dave Abraham has an article in which argument is returned by value. Here I reproduce a fragment; I highly recommend you read the entire article:
Be honest: what does the following code look like:
std::vector<std::string> get_names(); ... std::vector<std::string> const names = get_names();
Honestly, although I should know better, it makes me nervous. Basically, when get_names() returns, we should copy a vector from string s. Then we need to copy it again when we initialize names , and we need to destroy the first copy. If the vector has N string , each copy may require as many N + 1 memory allocations as an integer number of fuzzy cache access data> when copying the contents of a string.
Instead of confronting such an alarm, Ive often refused to pass by reference to avoid unnecessary copies:
get_names(std::vector<std::string>& out_param ); ... std::vector<std::string> names; get_names( names );
Unfortunately, this approach is far from ideal.
- Code increased by 150%
- We had to abandon
const -ness because there were mutating names. - As functional programmers like to remind us, mutation makes code more difficult to explain, undermining referential transparency and equational reasoning.
- We no longer have strict semantics of meanings for names.
But is it really necessary to spoil our code in such a way as to increase efficiency? Fortunately, the answer turns out to be negative (and especially if you use C ++ 0x).