C++ mutable appropriate in this case? - c++

I would like to ask if the use of mutable is appropriate here:
#include <iostream>
class Base
{
protected:
int x;
public:
virtual void NoMod() const
{
std::cout << x << std::endl;
}
void Draw() const
{
this->NoMod();
}
};
class Derive : public Base
{
private:
mutable int y;
public:
void NoMod() const
{
y = 5;
}
};
int main()
{
Derive derive;
// Test virtual with derive
derive.Draw();
return 0;
}
The Base class is a 3rd-party library. I'm extending it to provide my own NoMod(). The library original NoMod() is declared as a const.
My NoMod() differs from Base in the fact that it needs to modify its own member variable.
Thus, for my own NoMod() to compile and get called when Draw() is called, I had to
1) Implement Derive::NoMod() as a const
2) make my int y mutable.
Is this the best I can do?

It's hard to say, since you don't give any context on what y refers to or how it's used.
In general, mutable is only appropriate when changing the mutable variable doesn't change the actual "value" of the object. For example, when I was writing a wrapper for C-style strings, I needed to make the internal mLength variable mutable so that I could cache the length, even if the thing it was requested on was a const object. It didn't change the length or the string, and wasn't visible outside of the class itself, so making it mutable was okay.

As 'head geek' described, the answer to your question depends on how your data member is used.
I distinguish two types of data members in a class.
I use the common term 'attribute' to refer to data members
that are the logical state or 'value' of the object.
Typically attributes are rarely declared as mutable.
I have coined the protologism 'contribute' it denote
data members that are simply 'working memory/storage'
and that are somewhat divorced from the state of the object.
Contributes have no contextual relevance to the user of the object,
they exist in the class only to contribute to the maintenance
and efficient operation of the object.
Contributes are usually declared in the class as mutable and are always
private or protected.
For example let's say your object is a linked list,
so you have a pointer to the first item in the list.
I would consider this pointer a contribute because
it does not represent the data in the list.
Even if the list is sorted and the
pointer is set to the new first item in the list,
the user of the list object could care less how the
list is maintained. Only that the list data has
been modified or not and that the the list is sorted or not is
relevant to the user's perspective.
Even if you had a booean data member 'sorted' to quickly determine
if the list is in a sorted state, that too would be a contribute
because it is the list structure itself which imbues the sorted state,
the 'sorted' variable member is used simply to efficiently remember the state
without having to scan the list.
As another example, if you have a const method that searches the list.
Suppose you know that typically the search will return the
most recently previously searched for item,
you would keep a pointer in your class to such a item so your method
can first check if the last found item matches the search key before searching
the entire list (if the method does indeed need to search the list and finds
an item, the pointer would be updated).
This pointer I would consider to be a contribute because it
is only there to help speed up the search. Even though the
search updates the pointer contribute, the method is effectively
const because none of the items' data in the container are modified.
So, data members that are attributes are usually not declared mutable,
and data members that contribute to the functioning of an object will usually be mutable.

The only time I think mutable is okay is for things like reference counts that aren't really part of the object's state.
If y is part of the object's physical state, but not logical state, then this is okay, but otherwise, don't do it.

Use mutable when the member of the class is not really defining the state of the object, (e.g. is a cached value/object that helps improving performance).
I use to do another difference. In your example, you only enforce change to const object only once. You can use also const_cast operator:
const_cast< Derive*>( this)->y = 10;
When you use const_cast operator, you have the advantage that you can easily identify the places where you enforced the const to non-const conversion by simply running a search in your code for the operator name.
However, as I said, if the member is not part of the state of the object, but must be changed indirectly in several constant methods, use mutable for that member.

The only situations where I needed the mutable feature are:
a cached version of derived data. For example, if you have a Rectangle class that has a GetSurface() member function that is likely to be called a lot, you could add a mutable m_surfaceCache member variable to keep the derived data.
a critical section member variable. This is because my CriticalSection::Enter() function is conceptually not const, but the critical section member variable is not a real part of the class data, it is more like a compiler guideline.
However, as a general rule of thumb, I'dd advise not to use mutable too often, as it bypasses C++'s wonderful const feature.

Another situation where you can think of 'mutable' is when you have a class with 'const' member variables and you require to implement the assignment operator(=) without skipping the assignment of the 'const' member.
Also, const_cast apllied on originally declared 'const' variable and using it is U.B. according to C++ standard. So if the interface of a method accepts a 'const' which has to be modified internally, pass it a 'mutable' argument.
You may judge the appropriateness of the same from the above situations i.e. only of it makes sense semantically! Do not use it to make the source-code compilable.
Regards,

If, as you said, it's part of a third party library, you may not have a choice. C++ is at heart a pragmatic language and lets you do what you need to do, even if it may not always be a "best practice".
One thing to note though, is that the third party library is documenting that NoMod should not modify the object by adding that const specifier. By violating that contract, you leave yourself open to possible trouble. If the library in some situations call NoMod multiple times, your derived class better be able to handle that, since a true const method would have no problem with it.
I'd first look for another way to solve the problem, but failing there declare it mutable.

Related

Is using a reference as a return value considered as bad coding style?

I got a question regarding to these two possibilities of setting a value:
Let's say I got a string of a class which I want to change. I am using this:
void setfunc(std::string& st) { this->str = st; }
And another function which is able to do the exact same, but with a string reference instead of a void for setting a value:
std::string& reffunc() { return this->str; }
now if I am going to set a value I can use:
std::string text("mytext");
setfunc(text);
//or
reffunc() = text;
Now my question is if it is considered bad at using the second form of setting the value.
There is no performance difference.
The reason to have getters and setters in the first place is that the class can protect its invariants and is easier to modify.
If you have only setters and getters that return by value, your class has the following freedoms, without breaking API:
Change the internal representation. Maybe the string is stored in a different format that is more appropriate for internal operations. Maybe it isn't stored in the class itself.
Validate the incoming value. Does the string have a maximum or minimum length? A setter can enforce this.
Preserve invariants. Is there a second member of the class that needs to change if the string changes? The setter can perform the change. Maybe the string is a URL and the class caches some kind of information about it. The setter can clear the cache.
If you change the getter to return a const reference, as is sometimes done to save a copy, you lose some freedom of representation. You now need an actual object of the return type that you can reference which lives long enough. You need to add lifetime guarantees to the return value, e.g. promising that the reference is not invalidated until a non-const member is used. You can still return a reference to an object that is not a direct member of the class, but maybe a member of a member (for example, returning a reference to the first name part of an internal name struct), or a dereferenced pointer.
But if you return by non-const reference, almost all bets are off. Since the client can change the value referenced, you can no longer rely on a setter being called and code controlled by the class being executed when the value changes. You cannot constrain the value, and you cannot preserve invariants. Returning by non-const reference makes the class little different from a simple struct with public members.
Which leads us to that last option, simply making the data member public. Compared to a getter returning a non-const reference, the only thing you lose is that the object returned can no longer be an indirect member; it has to be a direct, real member.
On the other side of that equation is performance and code overhead. Every getter and setter is additional code to write, with additional opportunities for errors (ever copy-pasted a getter/setter pair for one member to create the same for another and then forgot to change one of the variables in there?). The compiler will probably inline the accessors, but if it doesn't, there's call overhead. If you return something like a string by value, it has to be copied, which is expensive.
It's a trade-off, but most of the time, it's better to write the accessors because it gives you better encapsulation and flexibility.
We cannot see the definition of the member str.
If it's private, your reffunc() exposes a reference to a private member; you're writing a function to violate your design, so you should reconsider what you're doing.
Moreover, it's a reference, so you have to be sure that the object containing str still exists when you use that reference.
Moreover, you are showing outside implementation details, that could change in the future, changing the interface itself (if str becomes something different, setfunc()'s implementation could be adapted, reffunc()'s signature has to change).
It's not wrong what you wrote, but it could be used in the wrong way. You're reducing the encapsulation. It's a design choice.
It's fine. However, you have to watch out for these pitfalls:
the referenced object is modifiable. When you return a non-const reference, you expose data without protection against modifications. Obvious, but be aware of this anyway!
referenced objects can go out of sope. If the referenced object's lifetime ends, accessing the reference will be undefined behavior. However, they can be used to extend the lifetime of temporaries.
The way you used the reffunc() function is considered bad coding. But (as mentioned in the comments), generally speaking, returning references is not bad coding.
Here's why reffunc() = text; is considered bad coding:
People usually do not expect function calls on the left hand of an assignment, but on the right side. The natural expectation when seeing a function call is that it computes and returns a value (or rvalue, which is expected to be on the right hand side of assignment) and not a reference (or lvalue, which is expected to be on the left hand side of assignment).
So by putting a function call on the left hand side of the assignment, you are making your code more complicated, and therefore, less readable. Keeping in mind that you do not have any other motivations for it (as you say, performance is the same, and it usually is in these situations), good coding recommends that you use a "set" function.
Read the great book "Clean Code" for more issues on clean coding.
As for returning references in functions, which is the title of your question, it is not always bad coding and is sometimes required for having cleaner and briefer code. Specifically many operator overloading features in c++ work properly if you return a reference (see operator[] in std::vector and the assignment operator which usually help the code become more readable and less complex. See the comments).

Should a C++ object always be in a valid state?

Whenever an object is constructed, should the constructor always leave it in an "initialised" state?
For example, if an Image class has two constructors where one takes a file path string, and the other takes no parameters, is it bad practice for the latter to leave the image object in an invalid state?
Assuming the class is written to handle both states.
I ask this because I find it almost necessary to have a default construct in a lot of cases. Especially when an object is a member of a class and you want to initialise it IN the constructor of that class.
EDIT: I am aware of the member initialiser list. I have found a few situations where I would like to construct the object DURING the constructor of the class it is held in, not before. Although, I understand that this could potentially be more dangerous than any other alternative.
It all boils down to the definition of a "valid state": if the methods of your class handle the state when the path is empty, then the state with the empty path is a valid state, and is definitely acceptable.
This may not be optimal from the coding perspective, though, because potentially you might need to add multiple checks for the path to be valid. You can often manage complexity by implementing the State Pattern.
I find it almost necessary to have a default construct in a lot of cases. Especially when an object is a member of a class and you want to initialise it IN the constructor of that class.
You do not need a default constructor in order to initialize an object in the constructor of the class of which it is a member, as long as you construct the dependent in the initialization list.
Your last line:
I ask this because I find it almost necessary to have a default construct in a lot of cases. Especially when an object is a member of a class and you want to initialise it IN the constructor of that class.
Implies that you are not using member initializer lists. You do not need a default constructor in this case. Example:
class Member {
public:
Member(std::string str) { std::cout << str << std::endl; }
};
class Foo {
public:
Foo() : member_("Foo") {}
private:
Member member_;
}
Additionally, your question title and body conflict and the terminology is a bit vague. When constructing, it is usually best to leave the object in a valid and usable state. Sometimes the second aspect (being usable) is less necessary, and many solutions require it. Further, in C++11, moving from an object must leave it in a valid state, but doesn't necessarily (and in many cases shouldn't) leave it in a usable state.
EDIT: To address your concern about doing work in your constructor, consider moving the work to either a static member of the Member class, or a private (static or non-static) function in the owning class:
class Member {
public:
Member(std::string str) { std::cout << str << std::endl; }
};
class Foo {
public:
Foo() : member_(CreateFoo()) {}
private:
Member CreateMember() {
std::string str;
std::cin >> str;
return Member(str);
}
Member member_;
};
One danger of this approach, however, is that the intialization order can be important if you use a non-static member function to do the creation. A static function is much much safer, but you may wish to pass some other pertinent member info. Remember that initialization is done in order of member declaration within the class, NOT initializer list declaration order.
Yes, it should always be valid. However, it is usually not very well defined what makes the object valid. At the very least, the object should be usable in a way without crashing. This, however, does not mean that all operations can be performed on the object, but there should be at least one. In many cases, that's just assignment from another source (e.g. std container iterators) and destruction (this one is mandatory, even after a move). But there more operations the objects supports in any kind of state, the less prone to error it will be.
It is usually a trade-off. If you can get away with objects only having states where all operations are valid, that's certainly great. However, those cases are rare, and if you have to jump through hoops to get there, it's usually easier to just add and document preconditions to some of its functionality. In some cases, you might even split the interface to differentiate between functions that make this trade-off and those that do not. A popular example of this is in std::vector, where you need to have enough elements as a precondition to using operator[]. On the other hand, the at() function will still work, but throw an exception.
First, let us define what exactly a "valid state" is: Its an state where the object could do its work.
For example, if we are writting a class that manages a file and let us to write and read the file, a valid state (following our definition) could be an state where the object is holding a correctly oppened file and its ready to read/write on it.
But consider other situation: Whats the state of a moved rvalue?
File::File( File&& other )
{
_file_handle = other._file_handle;
other._file_handle = nullptr; //Whats this state?
}
Its a state where the file object its not ready to write/read on a file, but is ready to be initialized. That is, is a ready to initialize state.
Now consider an alternative implementation of the above ctor using the copy and swap idiom:
File::File() :
_file_handle{ nullptr }
{}
File::File( File&& other ) : File() //Set the object to a ready to initialice state
{
using std::swap; //Enable ADL
swap( *this , other );
}
Here we use the default ctor to put the object on a ready to initialice state, and just swap the passed rvalue with this object, resulting on exactly the same behaviour as the first implementation.
As we have seen above, one thing is a ready to work state, a state where the object is ready to do whats supposed to do, and other completely different thing is a ready to initialize state: A state where the object is not ready to work, but is ready to be initialized and setted up to work..
My answer to your question is: An object is not alwways in a valid state (Its not allways ready to be used), but if its not ready to be used it should be ready to be initialized and then ready to work.
Normally, yes. I've seen a few good counterexamples but they are so rare.

is it good practice to add const at end of member functions - where appropriate?

Is it a good practice, in C++, to add const at the end of a member function definition every time the function does not modify the object, i.e., every time the function is 'eligible' for const?
I know that it's necessary in this case:
class MyClass {
public:
int getData() const;
};
void function(const MyClass &m) { int a = m.getData(); dosomething... }
but other than this, and other uses of const for actual functionality, does adding const to the end actually change the way code is executed (faster/slower) or is it just a 'flag' for the compiler to handle cases such as the one above?
In other words, if const (at the end) is not needed for functionality in a class, does adding it make any difference?
Please see this excellent article about const correctness by Herb Sutter (C++ standards committee secretary for 10 years.)
Regarding optimizations, he later wrote this article where he states that "const is mainly for humans, rather than for compilers and optimizers." Optimizations are impossible because "too many things could go wrong...[your function] might perform const_casts."
However, const correctness is a good idea for two reasons: It is a cheap (in terms of your time) assertion that can find bugs; and, it signals the intention that a function should theoretically not modify the object's external state, which makes code easier to understand.
every time the function does not modify the object, i.e., every time the function is 'eligible' for const?
In my opinion, Yes. It ensures that you call such functions on const objects or const expressions involving the object:
void f(const A & a)
{
a.inspect(); //inspect must be a const member function.
}
Even if it modifies one or few internal variables once or twice, even then I usually make it const member function. And those variables are declared with mutable keyword:
class A
{
mutable bool initialized_cache; //mutable is must!
public:
void inspect() const //const member function
{
if ( !initialized_cache)
{
initialized_cache= true;
//todo: initialize cache here
}
//other code
}
};
Yes. In general, every function that is logically const should be made const. The only gray areas are where you modify a member through a pointer (where it can be made const but arguably should not be const) or where you modify a member that is used to cache a computation but otherwise has no effect (which arguably should be made const, but will require the use of the keyword mutable to do so).
The reason why it's incredibly important to use the word const is:
It is important documentation to other developers. Developers will assume that anything marked const does not mutate the object (which is why it might not be a good idea to use const when mutating state through a pointer object), and will assume that anything not marked const mutates.
It will cause the compiler to catch unintentional mutations (by causing an error if a function marked const unintintionally calls a non-const function or mutates an element).
Yes, it is a good practice.
At the software engineering level it allows you to have read-only objects, e.g. you can prevent objects from being modified by making them const. And if an object is const, you are only allowed to call const functions on it.
Furthermore, I believe the compiler can make certain optimizations if it he knows that an object will only be read (e.g., share common data between several instances of the object as we know they are never being modified).
The 'const' system is one of the really messy features of C++. It is simple in concept, variables declared with ‘const’ added become constants and cannot be altered by the program, but, in the way is has to be used to bodge in a substitute for one of the missing features of C++, it gets horridly complicated and frustratingly restrictive. The following attempts to explain how 'const' is used and why it exists. Of the mixes of pointers and ‘const’, the constant pointer to a variable is useful for storage that can be changed in value but not moved in memory and the pointer (constant or otherwise) is useful for returning constant strings and arrays from functions which, because they are implemented as pointers, the program could otherwise try to alter and crash. Instead of a difficult to track down crash, the attempt to alter unalterable values will be detected during compilation.
For example, if a function which returns a fixed ‘Some text’ string is written like
char *Function1()
{ return “Some text”;}
then the program could crash if it accidentally tried to alter the value doing
Function1()[1]=’a’;
whereas the compiler would have spotted the error if the original function had been written
const char *Function1()
{ return "Some text";}
because the compiler would then know that the value was unalterable. (Of course, the compiler could theoretically have worked that out anyway but C is not that clever.)
When a subroutine or function is called with parameters, variables passed as the parameters might be read from to transfer data into the subroutine/function, written to to transfer data back to the calling program or both to do both. Some languages enable one to specify this directly, such as having ‘in:’, ‘out:’ & ‘inout:’ parameter types, whereas in C one has to work at a lower level and specify the method for passing the variables choosing one that also allows the desired data transfer direction.
For example, a subroutine like
void Subroutine1(int Parameter1)
{ printf("%d",Parameter1);}
accepts the parameter passed to it in the default C & C++ way which is a copy. Therefore the subroutine can read the value of the variable passed to it but not alter it because any alterations it makes are only made to the copy and lost when the subroutine ends so
void Subroutine2(int Parameter1)
{ Parameter1=96;}
would leave the variable it was called with unchanged not set to 96.
The addition of an ‘&’ to the parameter name in C++ (which was a very confusing choice of symbol because an ‘&’ infront of variables elsewhere in C generate pointers!) like causes the actual variable itself, rather than a copy, to be used as the parameter in the subroutine and therefore can be written to thereby passing data back out the subroutine. Therefore
void Subroutine3(int &Parameter1)
{ Parameter1=96;}
would set the variable it was called with to 96. This method of passing a variable as itself rather than a copy is called a ‘reference’ in C.
That way of passing variables was a C++ addition to C. To pass an alterable variable in original C, a rather involved method using a pointer to the variable as the parameter then altering what it pointed to was used. For example
void Subroutine4(int *Parameter1)
{ *Parameter1=96;}
works but requires the every use of the variable in the called routine so altered and the calling routine altered to pass a pointer to the variable which is rather cumbersome.
But where does ‘const’ come into this? Well, there is a second common use for passing data by reference or pointer instead of copy. That is when copying a the variable would waste too much memory or take too long. This is particularly likely with large compound user-defined variable types (‘structures’ in C & ‘classes’ in C++). So a subroutine declared
void Subroutine4(big_structure_type &Parameter1);
might being using ‘&’ because it is going to alter the variable passed to it or it might just be to save copying time and there is no way to tell which it is if the function is compiled in someone else’s library. This could be a risk if one needs to trust the the subroutine not to alter the variable.
To solve this, ‘const’ can be used the in the parameter list like
void Subroutine4(big_structure_type const &Parameter1);
which will cause the variable to passed without copying but stop it from then being altered. This is messy because it is essentially making an in-only variable passing method from a both-ways variable passing method which was itself made from an in-only variable passing method just to trick the compiler into doing some optimization.
Ideally, the programmer should not need control this detail of specifying exactly how it variables are passed, just say which direction the information goes and leave the compiler to optimize it automatically, but C was designed for raw low-level programming on far less powerful computers than are standard these days so the programmer has to do it explicitly.
My understanding is that it is indeed just a flag. However, that said, you want to add it wherever you can. If you fail to add it, and a function elsewhere in your code does something like
void function(const MyClass& foo)
{
foo.getData();
}
You will run into issues, for the compiler cannot guarantee that getData does not modify foo.
Making member functions const ensures that calling code that has const objects can still call the function. It is about this compiler check - which helps create robust self-documenting code and avoid accidental modifications of objects - and not about run-time performance. So yes, you should always add const if the nature of the function is such that it doesn't need to modify the observable value of the object (it can still modify member variables explicitly prefixed with the mutable keyword, which is intended for some quirky uses like internal caches and counters that don't affect the client-visible behaviour of the object).

How to implement class composition in C++?

If I understand correctly we have at least two different ways of implementing composition. (The case of implementation with smart pointers is excluded for simplicity. I almost don't use STL and have no desire to learn it.)
Let's have a look at Wikipedia example:
class Car
{
private:
Carburetor* itsCarb;
public:
Car() {itsCarb=new Carburetor();}
virtual ~Car() {delete itsCarb;}
};
So, it's one way - we have a pointer to object as private member.
One can rewrite it to look like this:
class Car
{
private:
Carburetor itsCarb;
};
In that case we have an object itself as private member. (By the way, am I right to call this entity an object from the terminology point of view?)
In the second case it is not obligatory to implicitly call default constructor (if one need to call non-default constructor it's possible to do it in initializer list) and destructor. But it's not a big problem...
And of course in some aspects these two cases differ more appreciably. For example it's forbidden to call non-const methods of Carburetor instance from const methods of Car class in the second case...
Are there any "rules" to decide which one to use? Am I missing something?
In that case we have an object itself as private member. (By the way, calling this entity as object am I write from the terminology point of view?)
Yes you can say "an object" or "an instance" of the class.
You can also talk about including the data member "by value" instead of "by pointer" (because "by pointer" and "by value" is the normal way to talk about passing parameters, therefore I expect people would understand those terms being applied to data members).
Is there any "rules" to decide which one to use? Am I missed something?
If the instance is shared by more than one container, then each container should include it by pointer instead of value; for example if an Employee has a Boss instance, include the Boss by pointer if several Employee instances share the same Boss.
If the lifetime of the data member isn't the same as the lifetime of the container, then include it by pointer: for example if the data member is instantiated after the container, or destroyed before the container, or destroyed-and-recreated during the lifetime of the container, or if it ever makes sense for the data member to be null.
Another time when you must including by pointer (or by reference) instead of by value is when the type of the data member is an abstract base class.
Another reason for including by pointer is that that might allow you to change the implementation of the data member without recompiling the container. For example, if Car and Carburetor were defined in two different DLLs, you might want to include Carburetor by pointer: because then you might be able to change the implementation of the Carburetor by installing a different Carburetor.dll, without rebuilding the Car.dll.
I tend to prefer the first case because the second one requires you to #include Carburettor.h in Car.h.
Since Carburettor is a private member you should not have to include its definition somewhere else than in the actual Car implementation code. The use of the Carburettor class is clearly an implementation detail and external objects that use your Car object should not have to worry about including other non mandatory dependencies. By using a pointer you just need to use a forward declaration of Carburettor in Car.h.
Composition: prefer member when possible. Use a pointer when polymorphism is needed or when a forward declaration is used. Of course, without smart pointer, manual memory management is needed when using pointers.
If Carb has the same lifetime as Car, then the non-pointer form is better, in my opinion. If you have to replace the Carb in Car, then I'd opt for the pointer version.
Generally, the non-pointer version is easier to use and maintain.
But in some cases, you can't use it. For example if the car has multiple carburetors and you wish to put them in an array, and the Carburetor constructor requires an argument: you need to create them via new and thus store them as pointers.

When is it preferable to store data members as references instead of pointers?

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