Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
When I was learning C++, I was told that if you want to have multiple classes reference the same object, you should give both a pointer to the object. In Modern C++, I'd probably interpret this as the object being a unique_ptr and the classes holding non-owning-raw-pointers.
Recently, my mentor at work suggested that you should only use pointers when you plan on having the store point to a different object or null at some point. Instead, you should store references in classes.
Reference member variables are a thing I've actually never seen before, so I was looking for advice on what the concerns were... It makes sense... You're saying that this reference is assumed to never be null... I guess the concern would then be that you couldn't /check/ for null. It would have to be an invariant of your class...
How about how this applies to using the references for polymorphism?
Update:
The answer that I selected covers my questions pretty well, but I thought I'd clarify for future readers. What I was really looking for was an idea of the consequences of using a reference rather than a pointer as a class member. I realise that the way the question was phrased made it sound more like I was looking for opinions on the idea.
Should I store references in classes in c++?
yes, why not. This question is IMO 'primarily opinion-based', so my answer is based on my own experience.
I use member references when I dont need what pointers have to offer, this way I limit possiblity that my class will be wrongly used. This means among other possibility to bind new value, assign nullptr, you cant take pointer to reference, you cannot use reference arithmetics - those features are missing in references. You should also remember that reference is not an object type, this means among others that if you put a reference as struct member, then it is no longer POD - i.e. you cannot use memcpy on it.
You should also remember that for classes which have non static reference member, compiler will not generate implicit constuctors.
For me this means references as variable members are mostly usefull when class is some kind of wrapper, or a holder. Below is an example which also shows an alternative implementation using pointer member type. This alternative implementation gives you no additional benefit to the reference one, and only makes it possible to introduce Undefined Behaviour.
struct auto_set_false {
bool& var;
auto_set_false(bool& v) : var(v) {}
~auto_set_false() { var = false; }
};
struct auto_set_false_ptr {
bool* var;
auto_set_false_ptr(bool* v) : var(v) {}
~auto_set_false_ptr() { *var = false; }
};
int main()
{
// Here auto_set_false looks quite safe, asf instance will always be
// able to safely set nval to false. Its harder (but not imposible) to
// produce code that would cause Undefined Bahaviour.
bool nval = false;
auto_set_false asf(nval);
bool* nval2 = new bool(true);
auto_set_false_ptr asf2(nval2);
// lots of code etc. and somewhere in this code a statement like:
delete nval2;
// UB
}
It is generally not a good idea to store references in a class because the class cannot be default constructed, copy assigned, move assigned, and the member cannot be changed (the reference cannot be rebound).
That renders the class uncopieable. It therefore cannot be copied, moved or placed in most containers. The far more flexible and less surprising solution is to store a pointer or a std::refernce_wrapper.
IMO references works like pointers.
The only difference is in dynamic_cast: a failed cast produces a nullpointer with pointers, and results in a throw an exception with references.
References are far better than pointers because of one reason: you don't have to play with nulls.
A reference can't be null and it is a big value to not have to check for nulls.
The small difficulty is that you have to assign reference member in a constructor.
But you can definitely change it later to other non-null value pointing to an object of a class of the member or subclass of this class.
So it supports inheritance like pointers do.
Related
I know this is a general question in C++, and my knowledge of it is all that needs to be improved in order to understand it.
But my problem is not knowing how to ask the question, so I'm having trouble googling it.
I want to initialize a pointer object of a class with a reference to a different class' object.
Assume we have two classes: One, Two.
I wanna do the following:
Two objOfTwo = Two(2):
One* objPointer[2] = { &objOfTwo, &objOfTwo };
The code is merely an example of what I want to do, so ignore the fact it's the same object for both indexes.
My question is how do I go about making sure this class accepts this type of initialization? A special constructor?
Thank you.
This question already has answers here:
Pointer vs. Reference
(12 answers)
Closed 9 years ago.
Lets assume we have an object created statically (Type mObject;) which is exposed to the programmer by using getObject() method. I wonder what are the advantages and disadvantages in getting the object in such ways?
Type* SomeClass::getObject() {
return &mObject;
}
// the programmer types
Type* obj = someClassObj.getObject();
obj->someMethod();
and this way:
Type& SomeClass::getObject() {
return mObject;
}
// the programmer types
Type& obj = someClassObj.getObject();
obj.someMethod();
In pure C++ we use pointers quite rarely. Especially raw pointers.
Most of the code deal with object instances. As C++ have references to refer to them by identity, unlike C, taking address and passing around a pointer is reserved for situations where it is a must. Like:
when you want NULL to indicate absence
when you want to switch to different objects (reassign the pointer)
when you transfer ownership
Your example fits neither category, so you use a reference. This carries the message to the user that an object will always be there. So there's most time little point to fix the obj, you can just go ahead with someClassObj.getObject().someMethod(). The first case wants a NULL check in between.
Returning a pointer raises a lot of ambiguity/questions (could it be NULL? must I delete it?), while returning a reference to this static instance introduces guarantees. Namely, that the object will always be allocated and will always return an instance (technically, that static instance may not be constructed if you access it during initialization).
Although it is implementation defined, all implementations I know of use pointers "under the hood" when passing by reference (in the worst case). So there is no added cost to using a reference unless a copy or promotion must be introduced.
In this case, you should return a reference. In most C++ circles, references are favored over pointers when they provide all the functionality you need.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
The community reviewed whether to reopen this question 8 months ago and left it closed:
Original close reason(s) were not resolved
Improve this question
I was coding up a C++ class today, and I wrote a function that took an argument as a reference rather than a pointer, something I rarely ever do. I've always passed by pointers. So I was about to change it back, and then I realized - I have no idea if I should, or if it even matters.
So I turn to you guys. I have three ways of passing parameters about:
//1: By pointer
Object* foo(Object* bar) {…}
//2: By reference
Object& foo(Object& bar) {…}
//3: By value (just for completeness)
Object foo(Object bar) {…}
Assuming #3's out for performance reasons (yes, I know compilers have gotten pretty good at this, but still), the other two are more or less equivalent.
So: What's the "best" method? Pointers? References? Some combination of the two? Or does it even matter? Technical reasons are the best, but stylistic reasons are just as good.
Update: I've accepted YeenFei's answer, since it deals with the difference that clinched it for me (even if I then pointedly ignored his advice - I like having NULL as an option...). But everyone made good points - especially GMan (in the comments), and Nemo, in the answer dealing with performance and passing by value. If you're here for answers, check them all!
I would suggest to pass your argument by reference if it is expected to be valid. This would be a by-design optimization and save you from defensive programming.
Reference cannot be null while pointer can.
If you are dealing with pointer, you will need to verify whether given pointer is valid (non-null) regardless it is in raw form or wrapped in managed container (shared_ptr), before using them.
So I am going to make the case for choice #3. Consider the following code:
struct Foo {
int x;
int y;
};
Foo
add(Foo a, Foo b)
{
Foo result;
result.x = a.x + b.x;
result.y = a.y + b.y;
return result;
}
Foo
add2(Foo &a, Foo &b)
{
Foo result;
result.x = a.x + b.x;
result.y = a.y + b.y;
return result;
}
Try examining the generated assembly. Notice how add is almost entirely register operations, nicely scheduled. Notice how add2 is lots of memory accesses without any reordering.
I wrote a main that called each of these functions 10 billion times. Result? add took 22 seconds, while add2 took 26 seconds. Even for this trivial example, that's 10-20% better performance for the pass-by-value version.
OK, so the structure is trivial. But so is the function. The more complex the function, the more likely the pass-by-value version is to be faster, because the compiler knows that the two arguments do not "overlap". This is a huge benefit to optimization.
Of course, this decision should primarily be based on the semantics of the function: Do you need NULL to be a legal value? If so, obviously you need a pointer. Do you need to modify the objects? Then use a pointer or a reference.
But if you do not need to modify the objects, prefer to pass them by value unless the objects are large and/or have a non-trivial copy constructor (e.g. std::string). If by-value really is too slow, pass by reference-of-const or pointer-to-const.
But do not underestimate the potential speed advantages of passing by value, which derive from the advantages of registers vs. memory and instruction reordering. And note that these advantages become more pronounced with every generation of CPU.
Passing by pointer and by reference are really the same, except in syntax. I prefer passing by pointer, because it makes things explicit:
Object bar;
ptr_foo(&bar); // bar may change
ref_foo(bar); // can bar change? Now I need to go look at the prototype...
val_foo(bar); // bar cannot change. (Unless you use references here and there)
The only technical preference between passing values and pointers, as you have touched on is if the class is large enough to make its passing slow.
References any day, if you're designing everything yourself. Idiomatic modern C++ should almost never have raw pointers sticking out anywhere. Dynamically allocated objects should travel in resource managing containers (shared_ptr or unique_ptr, or weak_ptr if applicable), but for most operations passing by (const) reference is the primary way to pass arguments that need to be modified or that are of a heavy-weight type. Don't forget that passing by value may be a viable option if you have movable types.
Use:
const reference if the object is not modified
pointer if the object is modified or can be null
value if the object is small and you care about performance or if you need a copy of the object inside the function. This allows the compiler to pick the best way to copy/move the argument.
std::unique_ptr if ownership is transferred to the function.
You can take a look at https://www.boost.org/doc/libs/1_51_0/libs/utility/call_traits.htm library, it converts the type to the best arguments type automatically.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I have joined a new group that has coding guidelines that (to me) seem dated.
But just rallying against the machine without valid backup is not going to get me anywhere.
So I am turning to SO to see if we can up with rational reasons for/against (hey I may be wrong in my option so both sides of the argument would be appreciated).
The guideline that is up for argument is:
Tip: Use pointers instead of references for return arguments.
void Func1( CFoo &Return ); // bad
void Func2( CFoo *pReturn ); // good
Justification:
When you use a reference, it looks the same as a value. The caller may be surprised that his value has been changed after calling the function. The callee may innocently modify the value without meaning to affect the caller's value. By using a pointer, it is clear to both the caller and callee that the value can be changed. Using references can be particularly misleading in code reviews.
When you use a reference, it looks the same as a value.
Only if you really aren't paying attention to what you are doing. Ok, sometimes that happens, but really... no amount of coding standards can correct for people not paying attention or not knowing what they are doing.
The caller may be surprised that his value has been changed after calling the function.
If you are surprised by what happens when you call a function, then the function is poorly documented.
Given a function's name, its parameter list, and perhaps some very brief and descriptive documentation, it should be eminently clear what the function does and what its observable side effects are (including whether any arguments are modified).
The callee may innocently modify the value without meaning to affect the caller's value.
If the function is const correct, then this isn't a problem. If the function isn't const correct, then it should be made const correct, if you can (retroactively making code const correct can be an absolute beating).
This rationale doesn't make much sense, though: when you are actually writing the code for a function, you should be able to see the declarations of the parameters. If the function is so long that you can't, it's time for refactoring.
By using a pointer, it is clear to both the caller and callee that the value can be changed.
This is not entirely correct. A function can take a pointer to const object, in which case the object cannot be changed.
Using references can be particularly misleading in code reviews.
Only if the people doing the code reviews don't know what they are doing.
All of that is well and good, but why should pass-by-reference be used instead of pass-by-pointer? The most obvious reason is that a reference cannot be null.
In a function that takes a pointer, you have to check that the pointer is not null before you use it, at least with a debug assertion. During a proper code review you have to analyze more code to be sure that you don't accidentally pass a null pointer to a function that doesn't expect one. I've found that it takes much longer to review functions that take pointer arguments for this very reason; it's so much easier to get it wrong when using pointers.
It seems to me that the proper use of const would (mostly) eliminate the need for that tip. The part that still seems useful is when reading caller code, seeing:
Func1(x);
it isn't quite clear what is being done with x (particularly with a nondescript name like Func1). Instead using:
Func2(&x);
with the above convention, indicates to the caller that they should expect x to be modified.
If you have not already, buy a copy of Herb Sutter and Andrei Alexandrescu's "C++ Coding Standards: 101 Rules, Guidelines and Best Practices." Read it. Recommend it to your co-workers. It's a good base for a local coding style.
In Rule 25, the authors recommend:
"Prefer passing by reference if the argument is required and the function won't store a pointer to it or otherwise affect its ownership. This states that the argument is required and makes the caller responsible for providing a valid object."
"Argument is required" means NULL is not a valid value.
One of the most frequent causes of defects is accidental de-referencing of null pointers. Using references instead of pointers in these cases can eliminate these at compile-time.
So you have a trade-off -- eliminate a frequent source of errors, or ensure understandability of calling code by means other than the function name. I personally lean toward eliminating risk.
While I wouldn't use the tip's advice myself, the justification is valid, which is why languages like C# introduced the out and ref keywords for use at the call site.
The best argument I can come up for against it is this: instead of requiring people to use pointers, you should instead require that people write function names that reflect what the function does. When I call std::swap, I know it's going to change the value of the arguments because the name implies that. On the other hand, if I were to call a function getSize, I wouldn't expect that to modify any arguments.
Coding standards are based on habits as much as common sense. Some of your coworkers may rely on years of ingrained assumptions that a parameter not passed by pointer won't change - have pity on them.
The important part of coding standards is not that they're optimal, but that they're adhered to by everybody so that there's some consistency to the body of code.
If they really want explicit mention of out parameters at the call site, they should actually require that instead of hacking around it by trying to make pointers mean something they don't. Pointers don't imply modification any more than references do, and it's not uncommon to pass pointers for non-modified objects.
One potential way to express out parameters explicitly:
template<class T>
struct Out {
explicit Out(T& obj) : base(obj) {}
T& operator*() { return base; }
T* operator->() { return &base; }
private:
T& base;
};
template<class T>
Out<T> out(T& obj) {
return Out<T>(obj);
}
void f(Out<int> n) {
++*n;
}
int main() {
int n = 3;
f(out(n));
cout << n << '\n';
}
And as a temporary measure until they change old code to this, you can make the Out convertible to a pointer and/or reference:
// in class definition
operator T*() { return &base; }
operator T&() { return base; }
// elsewhere
void old(int *p);
void g() {
int n;
old(out(n));
}
I went ahead and wrote the various classes required for this, and for in-out parameters, in a way that should degrade nicely. I doubt I'll be using that convention any time soon (in C++, at least), but it'll work for anyone that wants to make call sites explicit.
I found there are two schools of though about this:
(a) use a pointer to show a parameter may be modified
(b) use a pointer if and only if the parameter may be null.
I agree with your motivation for (a): when reading code, you can't know all declarations, even if a mouseover gives you the declaration of the function. Mousing over hundreds of functions in thousands of lines just takes time.
I certainly see a problem here if you mix in and out parameters:
bool GetNext(int index, Type & result);
A call to this fuinction would look like this:
int index = 3;
Type t;
if (!GetNext(index, t))
throw "Damn!";
In that example, the call itself is fairly obvious, to potentially modify t. But what about index? Maybe GetNext increments the index, so you always get the next item, without the callee needing to keep caller state?
Which usually raises the reply Then the method should be GetNextAndIncrementIndex, or you should use an iterator anyway. I bet these people never had to debug code written by electrical engineers that still think Numerical Recipes is the Holy Grail of programming.
Howver I still tend to (b): simply because the problem can be avoided for new code being written, and "may be null or not" is usually the more common problem.
The justification is logically true.
It may surprise coders that the value has changed (because they thought the value was being passed by value).
But does logically true provide any meaning in this context.
So the value may change. How does this affect the correctness of the code?
Apart from it may print out a different value then an illogical human expects, but the code is doing what it is supposed to be doing and the compiler is enforcing constraints.
i recommend:
pass by reference (do not pass by pointer)
pass by const reference wherever possible (assuming you've used const correctly throughout your codebase)
place arguments/parameters which mutate at the beginning of the list
label the function appropriately
label the argument appropriately (and create methods/functions with detailed and descriptive names and few arguments)
document the result
if multiple arguments/parameters mutate, consider creating a simple class which holds these arguments (even if by reference themselves)
if they still can't function (sic) without visual and documented cues, create a lightweight template container object for the parameter which mutates, which is then passed to the method or function
I would disagree with this guideline. The confusion mentioned in the justification can be easily resolved by making sure the code is const-correct. If you are passing an input parameter to a function by reference, then it should be a const reference. If the reference is not const, that is an indication that it is an output parameter, whose value may be changed by the function.
Furthermore, when you pass a pointer to a function, rather than a reference, that instantly raises a question about whether or not this is a pointer to dynamically allocated memory, and whether or not it should be freed. Using a reference removes the temptation to call delete.
There are times when passing a pointer is appropriate, such as when it actually is a pointer to a dynamically allocated object or array, or when it makes sense for it to be null. Although, you should prefer a smart pointer in such cases. In all other cases a reference is better, IMHO.
Let's say I have an object Employee_Storage that contains a database connection data member. Should this data member be stored as a pointer or as a reference?
If I store it as a reference, I
don't have to do any NULL
checking. (Just how important is NULL checking anyway?)
If I store it as a pointer, it's
easier to setup Employee_Storage
(or MockEmployee_Storage) for the
purposes of testing.
Generally, I've been in the habit of always storing my data members as references. However, this makes my mock objects difficult to set up, because instead of being able to pass in NULLs (presumably inside a default constructor) I now must pass in true/mock objects.
Is there a good rule of thumb to follow, specifically with an eye towards testability?
It's only preferable to store references as data members if they're being assigned at construction, and there is truly no reason to ever change them. Since references cannot be reassigned, they are very limited.
In general, I typically store as pointers (or some form of templated smart pointer). This is much more flexible - both for testing (as you mentioned) but also just in terms of normal usage.
It is almost never prefereable to store references as data members, and a lot of the time it is impossible. If the objects must be assignable (as they must to be stored in a standard library container), references cannot be used. Also, references cannot be reseated, so once a reference is initialised with an object, it cannot be made to refer to a different object.
See this question Should I prefer pointers or references in member data? for a more detailed discussion of the issue.
I was trying to figure this out myself, so might as well post it. I conclude it doesn't seem to be a good idea to use reference data member because you could inadvertently create an alias when you go to initialize it.
#include <iostream>
using namespace std;
class stuff
{
public:
explicit stuff(int &a):x(a) //you have to initialize it here
{
//body intialization won't work
};
int& x; //reference data member
};
int main()
{
int A=100;
stuff B(A);//intialize B.x
cout<<B.x<<endl;//outputs 100
A=50;//change A;
cout<<B.x<<endl; //outputs 50, so B.x is an alias of A.
system("pause");
return 0;
}
Given a choice, I like to use the most constrained type possible.
So if I don't need to support null objects I'd much prefer to declare a
Foo& m_foo;
member rather than a
Foo*const m_foo;
member, because the former declaration documents the fact that m_foo can't be null.
In the short term, the advantage isn't that great. But in the long run, when you come back to old code, the instant assurance that you don't have to worry about the case of m_foo being null is quite valuable.
There are other ways of achieving a similar effect. One project I worked on where they didn't understand references would insist any potentially null pointers be suffixed '00' e.g m_foo00. Interestingly, boost::optional seems to support references although I haven't tried it. Or you can litter your code with assertions.
Adding to this question..
Class with reference data member:
you must pass a value to the object at construction (not unexpectedly)
breaks the rule of encapsulation, as referenced variable can be changed from outside class, without class object having any control of it. (I suppose the only use case could be something like this though, for some very specialized reasons.)
prevents creating assignment operator. What are you going to copy?
you need to ensure the referred variable is not destroyed while your object is alive