Given the example:
inline string &GetLabel( ) {
return m_Label;
};
Where m_Label is a private class member variable.
The way I think I understand it, this function will return a reference to the variable m_Label. What would be the implications of using this throughout my program and would it be a better to just return the value, instead of the reference? Thank you!
The ampersand isn't before the function name so much as it's after the return type. it returns a reference to a string.
The implication of this is that a caller of this function could modify the value of m_label through the reference. On the other hand, it avoids copying the string. You might want the reference and the function to be const, like so:
inline const string& GetLabel() const
{
return m_Label;
}
Best of both worlds. You avoid the copy, but callers can't change your object.
It returns a reference to the private member.
There are many cases where this is desirable, but some care should be taken.
IMO it's generally not a good idea to return a copy of an internal object that is not an integral type, for overall performance reasons. Yes I know, premature optimization is not good, but this is not really optimization, it's just a good performance practice that allows the caller to determine the performance implications; if it wants a copy, it can just not declare the variable that it's assigning it to as a reference.
There are 2 general rules of thumb I use here:
1) If you don't want the caller to be able to modify the private object directly, declare the return value as a const reference:
inline const string& GetLabel() const{ return m_Label; }
2) A caller should never store the reference returned from a class method, it should only be used locally where the parent object is guaranteed to be in scope.
If for some reason you need callers to be able to store a reference to your internal objects, use smart pointers instead.
Returning a reference means that the calling code can modify the value of your member variable after you return. That's very dangerous, unless you intended for that to happen.
Better is a const reference, or return by value (without the &).
One implication is that if the enclosing object is destructed, the reference becomes invalid:
Object* o = new Object;
string& label = o->GetLabel();
delete o;
// label becomes a dangling reference here.
Another implication is that a caller may modify the string. You can remedy that by returning a const reference.
You're are correct. It's a reference to the string member.
The implication will be that if a caller were to assign a value or otherwise modify the returned string that they would also be modifying the member variable. If this is not the intent you may want to return a copy by value to avoid breaking encapsulation.
Related
class A
{
...
public:
shared_ptr<Logger> GimmeLogger () const
{
return m_logger;
}
private:
shared_ptr<Logger> m_logger;
};
In class A, should GimmeLogger be const or non-const?
It would make sense to be const because it is a simple getter that doesn't modify *this (syntactic const).
But on the other hand, it returns a non-const pointer to another object that it owns (semantically non-const).
If you make that non-const, then you cannot write this:
void f(const A & a)
{
auto v = a.GimmeLogger(); //error
}
So if you want to write this; that is, if you want to call GimmeLogger on const object, then make GimmeLogger a const member function, because you cannot invoke a non-const member function, on const object. However, you can invoke a const member function, on non-const object (as well as on const object).
Inside a const member function, every member is semantically const objects. So the type of m_logger in the function becomes const share_ptr<const m_logger>. So change the return type accordingly.
Because const is a keyword, it is checked syntactically, but it should be used semantically, that is, in your design operations that don't change the visible state of your class should be marked as const.
That is the whole idea behind the mutable keyword: adding the ability to mark a member as this does not take part of the visible state of the object so that the syntactic check matches the semantic meaning. In your particular case, because you are copying a pointer, you don't even need to use mutable there (this is one of the weak points of const-correctness actually, as returning a non-const pointer does not trigger errors while compiling, even though you are opening a door for changes in your object)
In this particular case, on the other hand, I don't see a good reason by which the object would publicize it's logger... That is, const-correctness aside, why do you need to grant access to the logger?
Yes, it should be const. The const-ness of the function has nothing to do with the const-ness of the return type.
I get your point, but I think the function remains const either way.
Generally you shouldn't return a handle to a member data when you can avoid it. Try hard to review your design and find a way around this. That said, if you must, it should be const. This allows you to call the function on const objects as well as non-const objects. See for example std::string::c_str(). You can also overload the function so you get both, like standard containers do with iterators.
When in doubt, look in the standard library for a hint.
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++?
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.
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.
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 your 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.
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.
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.
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;
I believe the second implementation (const reference) is correct as:
the returned object is immutable and therefore upholds the rules of encapsulation.
it's slightly more efficient as there is no copying of str.
However the first approach will work almost as well.
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;
}
I have a place in the code that used to say
const myType & myVar = someMethod();
The problem is that:
someMethod() returns const myType
I need to be able to change myVar later on, by assigning a default value if the object is in an invalid state. So I need to make myVar to be non-const.
I assume I need to make myVar be non-reference as well, right? E.g. myType myVar?
What is the C++ "correct" way of doing this const-to-nonconst? Static cast? Lexical cast? Something else?
I may have access to boost's lexical cast, so I don't mind that option, but I'd prefer the non-boost solution as well if it ends up i'm not allowed to use boost.
Thanks!
You probably don't need any cast. If you can copy a T, then you can also copy a T const, pathological cases excluded. The copy of the T const need not be a T const itself.
myType myVar = someMethod(); // Creates a non-const copy that you may change.
I wouldn't use the const_cast solutions, and copying the object might not work. Instead, why not conditionally assign to another const reference? If myVar is valid, assign that. If not, assign the default. Then the code below can use this new const reference. One way to do this is to use the conditional expression:
const myType& myOtherVar = (myVar.isValid() ? myVar : defaultVar);
Another way is to write a function that takes a const reference (myVar) and returns either myVar or defaultVar, depending on the validity of myVar, and assign the return value from that to myOtherVar.
A third way is to use a const pointer, pointing it at either the address of myVar or the address of the default object.
const_cast<type without const>()
But, does someMethod() really return const myType? If so, you are making a reference to a temporary -- it will be destroyed and your reference will be bad. Change myVar to non-ref (so it copies) -- no need to declare it const in that case. Or, if someMethod() returns a reference, use the const_cast if you must (but you are changing something that someMethod thought wouldn't change).
There's no "C++" way (not only to this, but to anything).
The bad way is to use a const_cast, but the behavior will then be undefined (read: don't do that).
What you should do is copy the object and then modify the copy. It's the only proper way to deal with immutable objects.
Try the following
myType& mutableMyVar = const_cast<myType&>(myVar);
In general removing const is a bad idea though. The caller method returned you a reference to a variable it believes will be treated as const. If you violate this assumption by removing the const and modifying the variable you could put either object into a valid state.
It may be legal in your particular case but in general this is something to be avoided
You can creat an object from the const object using copy constructor or something assignment operator and then modify it.
But I think you would be better off seeing why the function was returning const type in the first place. There would have been a reason why it was declared const. If you are very sure that that is what you wanted, you can always const_cast away the constness like this:
T obj1 = const_cast<T&> (obj);
What is the C++ "correct" way of doing this const-to-nonconst? Static cast? Lexical cast? Something else?
There is no C++ way. For one reason or another, the author of that class decided that you should not be able to modify the instance through this method.
If you were the author, you could make it return a non-const reference. But those are still suspicious, unless the class really has no business hiding it from you (e.g like vector doesn't hide what it holds for you, and just hides how it holds stuff for you).
A better way (depending on what this is all about) might also be not to expose members for external manipulation, but rather provide a method that does this manipulation for you. For example:
class BadPosition
{
int x, y;
public:
int& get_x() { return x; }
int& get_y() { return x; }
//...
};
BadPosition p;
p.get_x() += 1;
p.get_y() += -1;
class BetterPosition
{
int x, y;
public:
void move(int x_inc, int y_inc) { x += x_inc; y += y_inc; }
//...
};
BetterPosition p;
p.move(1, -1);
If you need this to put the class in a valid state later, then perhaps consider making its constructor do that. If you cannot do that, at least provide an Init() method, so as not to make such a complicated class rely entirely on being externally manipulated into something usable.
There may be of course other ways not requiring a cast, e.g you could create a copy, modify that, and then use the modified copy to replace the whole instance with another one (assuming this is enough to construct it):
X x;
...
Y y = x.get();
y.modify();
x = X(y);
Edit: So the class returns by value? In this case there should be no way to modify the instance in the class, since all you get is a copy in the first place. You can reference that with a const reference, but even if you cast away constness from that reference, you are still referencing a temporary.
My reply above assumed it returned a const reference, since that would seem a more sensible thing to do (I haven't seen people often return by const value, although probably there are those who strongly recommend it).
I am programming in C++ more then 5 years, and have never met any place where reference of the variable is recommended to use except as a function argument (if you don't want to copy what you pass as your function argument). So could someone point cases where C++ variable reference is recommended (I mean it gives any advantage) to use.
As a return value of an opaque collection accessor/mutator
The operator[] of std::map returns a reference.
To shorten the text needed to reference a variable
If you miss old-school with Foo do ... statement (that's Pascal syntax), you can write
MyString &name = a->very->long_->accessor->to->member;
if (name.upcase() == "JOHN") {
name += " Smith";
}
another example of this can be found in Mike Dunlavey's answer
To state that something is just a reference
References are also useful in wrapper objects and functors--i.e. in intermediate objects that logically contact no members but only references to them.
Example:
class User_Filter{
std::list<User> const& stop_list;
public: Functor (std::list<User> const& lst)
: stop_list(lst) { }
public: bool operator()(User const& u) const
{ return stop_list.exists(u); }
};
find_if(x.begin(),x.end(),User_Filter(user_list));
The idea here that it's a compile error if you don't initialize a reference in constructor of such an object. The more checks in compile time--the better programs are.
Here's a case where it's handy:
MyClass myArray[N];
for (int i = 0; i < N; i++){
MyClass& a = myArray[i];
// in code here, use a instead of myArray[i], i.e.
a.Member = Value;
}
Use references wherever you want, pointers when you are forced to.
References and pointers share part of their semantics: they are an alias to an element that is not present. The main difference is with memory managements: references express clearly that you are not responsible for the resource. On the other hand, with pointers it is never really clear (unless you mean smart pointers): are you assumed to delete the pointer or will it be deleted externally?
You must use pointers when you must manage memory, want to allow for optional semantics or need to change the element referred to at a later time.
In the rest of cases, where you can use a reference or a pointer, references are clearer and should be preferred.
Now, as you point out, they are really not needed: you can always use pointers for all the reference uses (even parameter passing), but the fact that you can use a single tool for everything does not mean there are no better suited tools for the job.
I tend to use reference members instead of pointers for externally controlled non-optional construction parameters.
EDIT (added example):
Let's say that you have a database and a DAO class having the database as a dependency:
struct Database {};
struct PersonDao {
const Database &m_d;
PersonDao(const Database &d): m_d(d) {}
};
Furthermore, the scope of the database is controlled externally from the DAO:
int main() {
Database d;
PersonDao pd(d);
}
In this case it makes sense to use a reference type, since you don't ever want DAO::m_d to be null, and its lifetime is controlled externally (from the main function in this case).
I use references in function arguments not just to avoid copies but also instead of pointers to avoid having to deal with NULL pointers where appropriate. Pointers model a "maybe there's a value, but maybe not (NULL)", references are a clear statement that a value is required.
... and to make it absolutely clear (-> comments). I tend to avoid pointers to model "maybe there are several values" - a vector is a better option here. Pointers to several values often end up in C-style programming because you usually have to pass the # of elements as well separately.
Use a const reference to give a name to a value, e.g.:
const Vec3 &ba=b-a;
This names the value, but doesn't necessarily create a variable for it. In theory, this gives the compiler more leeway and may allow it to avoid some copy constructor calls.
(Related non-duplicated Stack Overflow question at Const reference to temporary. The Herb Sutter link there has more information about this.)
The argument to the copy-constructor MUST be passed as a reference, since otherwise the copy constructor would need to call it self in an endless recursion (stack overflow).
I tend to agree, but perhaps const return values.
Well you kind of have two choices for aliasing other values(ignoring shared_ptrs and the like): pointers and references.
References must be initialized at construction to refer to something else. So semantically a reference can never be NULL. In reality, though, the underlying data can go away, giving you problems often more difficult to debug than if a pointer went away. So I'm not sure there's a real advantage here unless you were disciplined and consistent with how they were used vis-a-vis referring to items that were dynamically allocated. If you did this with pointers too, you'd avoid the same problems.
Perhaps more importantly, references can be used without thinking about all the issues that arise with pointers. This is probably the main advantage. Semantically a reference is the thing. If you guarantee as the caller/callee that the underlying memory doesn't go away, you don't have to confuse the user with any of the questions that come along with pointers (Do I need to free this? Could this be NULL? etc) and can safely use a reference for convenience.
An example of this might be a function that looks up the corresponding string for an enum,
const std::string& ConvertToString( someEnum val)
{
static std::vector< std::string > lookupTable;
if (lookupTable.empty())
{
// fill in lookup table
}
// ignoring the cast that would need to happen
return lookupTable[val]
}
Here the contract between the caller and the callee guarantees that the return type will always be there. You can safely return a reference, and avoid some of the questions that pointers invite.
References make code prettier. So use them whenever it takes a reference to beautify your code.
i would like to enlist some cases:
1) while writing singleton classes
class singleton
{
singleton();
explicit singleton(const singleton&);
singleton& operator=(const singleton&);
public:
static singleton& instance()
{
static singleton inst;
return inst;
}
};// this is called the 'Meyers' singleton pattern. refer to More Effective C++ by Scott Meyers
it has all the benefits, but avoids using the new operator
**2)**here is no such thing as a null reference. A reference must always refer to some object. As a result, if you have a variable whose purpose is to refer to another object, but it is possible that there might not be an object to refer to, you should make the variable a pointer, because then you can set it to null. On the other hand, if the variable must always refer to an object, i.e., if your design does not allow for the possibility that the variable is null, you should probably make the variable a reference
**3)**Because a reference must refer to an object, C++ requires that references be initialized:
string& rs; // error! References must
// be initialized
string s("xyzzy");
string& rs = s; // okay, rs refers to s
Pointers are subject to no such restriction
The fact that there is no such thing as a null reference implies that it can be more efficient to use references than to use pointers. That's because there's no need to test the validity of a reference before using it
**4)**Another important difference between pointers and references is that pointers may be reassigned to refer to different objects. A reference, however, always refers to the object with which it is initialized: ยค Item M1, P10
string s1("Nancy");
string s2("Clancy");
string& rs = s1; // rs refers to s1
string *ps = &s1; // ps points to s1
rs = s2; // rs still refers to s1,
// but s1's value is now
// "Clancy"
ps = &s2; // ps now points to s2;
// s1 is unchanged
Stream operators are an obvious example
std::ostream & operator<< (std::ostream &, MyClass const &...) {
....
}
mystream << myClassVariable;
You obviously don't want a pointer as checking for NULL makes using an operator very tedious i.s.o. convenient
I've used a reference to an ostream instead of a pointer. I supppose that I prefer references to pointers when the class has a lot of operators.
What's better as default, to return a copy (1) or a reference (2) from a getter function?
class foo {
public:
std::string str () { // (1)
return str_;
}
const std::string& str () { // (2)
return str_;
}
private:
std::string str_;
};
I know 2) could be faster but don't have to due to (N)RVO. 1) is safer concerning dangling references but the object will probably outlife or the reference is never stored.
What's your default when you write a class and don't know (yet) whether performance and lifetime issues matter?
Additional question: Does the game change when the member is not a plain string but rather a vector?
Well it really depends on what you expect the behaviour to be, by default.
Do you expect the caller to see changes made to str_ unbeknownst(what a word!) to them? Then you need to pass back a reference. Might be good if you can have a refcounted data member and return that.
If you expect the caller to get a copy, do 1).
My rule of thumb is to return a copy for simple basic datatypes such as int, string etc. For a bit more complicated structures where copying may be costlier (like vector you mentioned) I prefer to return a const-reference.
The compiler will not be able to perform (N)RVO in this case. The (named) return value optimization is an optimization where the compiler creates the function auto variables in the place of the return value to avoid having to copy:
std::string f()
{
std::string result;
//...
return result;
}
When the compiler sees the code above (and assuming that if any other return is present it will also return the result variable) it knows that the variable result has as only possible fate being copied over the returned temporary and then destroyed. The compiler can then remove the result variable altogether and use the return temporary as the only variable. I insist: the compiler does not remove the return temporary, it removes the local function variable. The return temporary is required to fulfill the compilers call convention.
When you are returning a member of your class, the member must exist, and the call convention requires the returned object to be in a particular location (stack address usually). The compiler cannot create the method attribute over the returned object location, nor can it elide making the copy.
I'm returning a reference, because a string seems not "cheap to copy" to me. It's a complex data type with dynamic memory management and all that.
The "if you want the caller to get a copy, you should return by value" argument is moot, because it doesn't preclude copies at all. The caller can still do the following and get a copy anyway
string s = obj.str();
You need to explicitly create a reference on the caller side to be able to refer to the data member directly afterwards - but why would you do that? There definitely are enough user defined types that are cheap to copy
Smart Pointers
Iterators
All of the non-class types.
Returning a reference to an object's internals as part of its public interface can be a code smell if not outright bad design.
Before returning a reference to an internal object in a public interface, the designer should pause. Doing so couples users of your class to part of your design. Often it is outright unnecessary, sometimes it indicates further design work is needed. At times it is necessary, as commenters have noted.
If there is no special reason to use a value type as return value, I always return a const reference. If I need (or expect to need) a (writable) copy, I add a copy ctor and an assignment operator to the returned class if not already available. For the usage think of:
const MyClass & ref = container.GetAt( 1234 ); // need only reference
MyClass copy = container.GetAt( 1234 ); // get writable copy
Actually this is quite straight forward, isn't it?
if its a small basic type - primatives like int and long and their wrappers and other basic things like 'Point' - return a copy
if its a string, or any other complex type - return a reference.
The only problem I have with returning a const-reference, which is something I would typically do for non basic types, is that there is nothing to stop the caller removing the "const"ness and then modifying the value.
Personally, I'd suggest that such code is a bug. If they know you're returning a reference and continue to cast away the const then it's on their head.