Return const reference to object instead of copy

During code refactoring, I came across some getter methods that return std :: string. Something like this, for example:

class foo { private: std::string name_; public: std::string name() { return name_; } }; 

Of course, a getter would return const std::string& ? The current method returns a copy that is not so efficient. Could there be a problem with returning a const link?

+67
c ++ const
Sep 25 '08 at 17:33
source share
12 answers

The only way that can cause the problem is that the caller saves the link rather than copying the string and trying to use it after the destruction of the object. Like this:

 foo *pFoo = new foo; const std::string &myName = pFoo->getName(); delete pFoo; cout << myName; // error! dangling reference 

However, since your existing function returns a copy, you are not breaking existing code.

+50
Sep 25 '08 at 17:41
source share

In fact, another problem specifically with returning a string not by reference is that std::string provides access through a pointer to an internal const char* via c_str () . This caused me many hours of headache debugging. For example, let's say I want to get the name from foo and pass it to JNI to use to build a jstring to go to Java later, and that name() returns a copy, not a link. I could write something like this:

 foo myFoo = getFoo(); // Get the foo from somewhere. const char* fooCName = foo.name().c_str(); // Woops! foo.name() creates a temporary that destructed as soon as this line executes! jniEnv->NewStringUTF(fooCName); // No good, fooCName was released when the temporary was deleted. 

If your caller will do such things, it might be better to use some kind of smart pointer or constant reference, or at least have an unpleasant warning comment header over your foo.name (). I mention JNI because former Java coders could be especially vulnerable to this type of method chain, which might seem otherwise harmless.

+25
Feb 23 '11 at 18:19
source share

One problem for returning a reference to a constant would be if the user encoded something like:

 const std::string & str = myObject.getSomeString() ; 

When std::string returned, the temporary object will remain alive and bound to str until str leaves the scope.

But what happens to const std::string & ? I assume that we will have a const reference to an object that can die when its parent object releases it:

 MyObject * myObject = new MyObject("My String") ; const std::string & str = myObject->getSomeString() ; delete myObject ; // Use str... which references a destroyed object. 

So, I prefer returning the const link (because, in any case, I'm just more comfortable sending the link than hoping the compiler will optimize the extra temporary) if the following contract is followed: "if you want it to be above my existence object, they copy it until the destruction of my object "

+16
Sep 25 '08 at 20:58
source share

Some std :: string implementations exchange memory with copy-on-write semantics, so return-by-value can be almost as efficient as return-by-reference, and you don't have to worry about life issues (runtime does this for you).

If you are worried about performance, then compare it (<= can't stress it enough) !!! Try both approaches and measure the gain (or lack thereof). If someone is better and you don't care, then use him. If not, then prefer by value for the protection that he offers, again with respect to life problems mentioned by other people.

You know what they say about assumptions ...

+10
Sep 25 '08 at 21:33
source share

Ok, so the differences between returning a copy and returning a link:

  • Performance . Return links may or may not be faster; it depends on how std::string is implemented by your compiler implementation (as others have pointed out). But even if you return the link, the destination after calling the function usually includes a copy, as in std::string name = obj.name();

  • Safety Returning the link may or may not cause problems (broken link). If users of your function do not know what they are doing, saving the link as a link and using it after the object-object goes out of scope, a problem occurs.

If you want fast and safe , use boost :: shared_ptr . Your object can internally save the string as shared_ptr and return shared_ptr . Thus, copying the object will not occur, and it will always be safe (unless your users pull the raw pointer using get() and start working with it after your object goes beyond the bounds).

+6
Mar 31 '09 at 14:58
source share

I would modify it to return const std :: string &. The caller is likely to make a copy of the result anyway, unless you change the entire calling code, but it will not create any problems.

One potential wrinkle occurs if you have multiple threads calling name (). If you return the link, but then change the base value, the caller value will change. But the existing code does not seem thread safe anyway.

Take a look at Dima’s answer to a related potential but unlikely problem.

+4
Sep 25 '08 at 17:34
source share

It can be assumed that you could break something if the caller really wanted to get a copy because they were going to change the original and wanted to keep a copy of it. However, it is much more likely that it really should just return a constant reference.

The simplest thing is to try and then test it if it still works, provided that you have some kind of test that you can run. If not, I would first focus on writing the test before proceeding with refactoring.

+3
25 Sep '08 at 17:37
source share

Does it matter? Once you use the modern optimizing compiler, functions that return by value will not include a copy if they should not be semantically required.

See C ++ lite FAQs .

+2
Sep 25 '08 at 18:59
source share

The odds are pretty good that the typical use of this function will not be broken if you go to the const link.

If all the code calling this function is under your control, just make changes and see if the compiler complains.

+1
25 Sep '08 at 17:43
source share

Depends on what you need to do. Perhaps you want all callers to change the return value without changing the class. If you return a link to const that will not fly.

Of course, the next argument is that the caller can then make his own copy. But if you know how the function will be used and know that this happens anyway, then perhaps this will help you take a step later in the code.

0
Sep 25 '08 at 17:35
source share

I usually return const & if I cannot. QBziZ gives an example of where this happens. Of course, QBziZ also claims that std :: string has copy-to-write semantics, which is rarely the case today because COW involves a lot of overhead in a multi-threaded environment. By returning const, you put a burden on the caller to do the right thing with a line at their end. But since you are dealing with code already in use, you probably should not change it unless profiling shows that copying this line causes serious performance problems. Then, if you decide to change it, you will need to check to make sure that you have not broken anything. I hope that other developers with whom you work do not make fragmentary material, as in Dima’s response.

0
Sep 25 '08 at 18:33
source share

Returning a reference to an element provides an implementation of the class. This can prevent class changes. May be useful for private or protected methods if optimization is required. What should return to the receiver C ++

0
Mar 20 '17 at 7:44
source share



All Articles