I am learning C++ from a background of mostly C and Java and I am curious on what is the best way to return an object in C++ without having to copy the object. From my understa
By default you should simply pass things by value. If a function does not need to modify or copy a parameter then it can be taken by const&
, but otherwise just take parameters by value. Return objects by value and leave it to move semantics or RVO to avoid a copy.
C++ uses and encourages passing objects 'by-value'. Move semantics are a feature that allows code to do this while making fewer copies than before they were introduced. Typically code does not need to use rvalue reference types directly in order to gain the benefit of move semantics. This is because temporary objects are rvalues and overload resolution will automatically select methods that take rvalue references.
For example:
std::string getStr(){
return "Hello";
}
std::string hello = getStr();
This code uses move semantics. return "Hello"
constructs a string temporary and so the constructor used to initialize the return value object will be the move constructor (though actually the return value optimization will almost certainly avoid this move). Then the value returned by getStr()
is a temporary, so the constructor selected for string hello
is again the move constructor.
I think you can also do std::string &&hello = getStr();
, but it's probably not necessary since hello
will already be move constructed.
Another way I could think of is using a shared pointer
I don't think smart pointers are a generally a good idea unless you really need the specific ownership semantics they provide. Using straightforward 'by-value' passing is a good default and move semantics generally allow you to use it without extra copying.
Also is it recommended that fields in a class be rvalue references if they won't be set using the constructor?
No, member references are not usually a good idea. They make things more complicated and you aren't even allowed to use them as your example shows. If your example code were allowed then sh.str = getStr();
would be undefined behavior, because you're trying to assign to a non-existant object. It's like std::string *str; *str = getStr();
.