Passing a noncopyable class - c++

I am reading a book and the author has a noncopyable class which ends up as a member variable of another class. It stuck out to me, because of the way the author did it and because he preferred a pointer to a reference. Let me give an example.
class Foo; // noncopyable
class WrapperFoo
{
public:
explicit WrapperFoo(Foo& x)
: mFoo(&x)
{}
Foo* mFoo;
};
What the author did that surprised me was he passed the Foo object by reference and then he takes the address of the Foo object and contructs the mFoo pointer. Why start with a reference to end with a pointer?
class Foo; // noncopyable
class WrapperFoo
{
public:
explicit WrapperFoo(Integer* x)
: mFoo(x)
{}
Integer* mFoo;
};
If I wanted a pointer this seems more straightforward (and identical). I do understand this may just be preference.
class Foo; // noncopyable
class WrapperFoo
{
public:
explicit WrapperFoo(Integer& x)
: mFoo(x)
{}
Integer& mFoo;
};
Further, I've read to prefer references to pointers, so why not this?
I believe the three examples are accomplishing the same task. Am I missing something? Why might the author prefer pointers to references in this example? Finally, is there a name for this usage?

Passing the reference prevents you from passing a NULL pointer to the Constructor. It guarantees that the object exists during creation.

Having references as data members is more often than not unpleasant as they have to be initialized in the initializer list (at object creation time, this has some implications such as the type being non-assignable). It's generally a better idea just to keep a pointer - although if it's an owning pointer, then might as well use the std::shared_ptr or std::unique_ptr.
As to why he used the take by reference and then he took the address, well, it was to avoid the reference as a data member AND keep the interface to the call simple (so that arg instead of &arg can be used.)

My guess about authors intentions would be that taking reference instead of pointer means that we are guaranteed at object creation time that the address contains valid object. A storage of pointer makes object copyable and, if needed, rebindable.
Though none of the approaches guarantees that passed object is stays valid after object creation.

Related

Storing a reference within class

I'm trying to keep a reference to a pointer of a different class in my class. I'm trying to see if there is a way to do this without having to define it in the ctor. I cannot make a copy, as I'm using that specific pointer returned to do other things.
class MyClass {
private:
OtherClassPtr &m_ptr_ref;
public:
MyClass();
public:
void MyFunction() {
m_ptr_ref = otherClassPtr->GetPtrRef();
if(!m_ptr_ref)
return;
}
};
A reference needs to be initialized at the point of declaration, and cannot change to refer to a different object during its lifetime. Thus you need to set it in the constructor.
An alternative is to store a pointer. I think of a reference as a pointer with nicer syntax, though the different syntax gives it a different semantic meaning; it acts like the object that it refers to, and so has the same value and the same address as that object. Most relevant to your question, the assignment operator works like assignment to the object, rather than a pointer. This is the reason it cannot change referent.
You can keep a pointer to the pointer:
OtherClassPtr* m_ptr_ref;
/* ... */
m_ptr_ref = &otherClassPtr->GetPtrRef();
An alternative is to use std::reference_wrapper, but that is nothing more than a fancy pointer, and I don't see the advantage over using a pointer.

If you want to return a member by reference, what is the best way to define it?

I'm having trouble choosing between two options. If you want to have a function returning a class member by reference, how should the class member be defined ?
MemberClass m_member ?
MemberClass* m_member ?
Let's say m_member is a member of type MemberClass(*) of the class MyClass.
If I do the first option, I have this :
.h
MemberClass &getMember(){return m_member;} //getter to the member, returns by reference
MemberClass m_member;
.cpp
//MyClass constructor
MyClass::MyClass(QObject * parent) :
QObject(parent),
m_member(MemberClass(this)),
...
Second option :
.h
MemberClass &getMember(){return *m_member;} //getter to the member, returns by reference
MemberClass* m_member;
.cpp
//MyClass constructor
MyClass::MyClass(QObject * parent) :
QObject(parent)
{
m_member = new MemberClass(this);
...
What is the best way of doing that ?
Plus, I realised that with the first option I was forced into implementing operator= and copy constructor for MemberClass, why is that ?
EDIT
I want m_member to live outside the class.
MemberClass is in fact a Controller (like in the MVC Design Pattern)
and I have to use it many times in the code.
MyClass is in charge of instanciating the Controller of class
MemberClass and some others and provide a getter to their instance
m_member cannot be NULL
it would be great if m_member was unique, to do that I put its constructor to protected and registered MyClass as a friend class
It actually depends on whether your member can be NULL. If it can not - use first option, if it can - use second one. Also in you first case you should use m_member(this), not m_member(MemberClass(this)).
Also consider adding const getter which can be used on const-objects:
const MemberClass &getMember() const {
return m_member;
}
Also note, that your second code is pretty dangerous. Try to avoid raw pointers when possible and use std::unique_ptr when necessary.
EDIT:
If m_member should be just a reference to some MemberClass than you should never use first option as it is going to create another instance of the MemberClass. In this case use reference MemberClass& m_member if MyClass is guaranteed to live longer than MemberClass and reference should not be changed to point to another instance (because you can't do that with C++ references). Consider using std::shared_ptr<MemberClass> in other cases.
Instead of using a raw pointer or having an automatic object I suggest you use a std::shared_ptr. If you have an automatic storage member like your first example you will not be able to keep it alive after the class is destroyed and allow the object and whatever has a handle to the member to modify the same object. If you use a pointer you can transfer ownership but know you class gets more complicated as you have to implement the rule of 3 and you have to keep track of who has a handle.
If you use a std::shared_ptr then you can return that pointer by value from getMember and now whoever got that handle shares in the ownership of the member. If the object is destroyed then whoever still has handle still has a valid object as there are still instances of the pointer in your code. If all of the things who had a handle to the member are gone and then you object is destroyed the pointer will be deleted for you as the last holder of the pointer was destroyed. Now there is no more manual memory management, the default constructors will work and you have expressed your intent on how the ownership of member should behave. That's a win-win-win.
I believe the first way is the better way of doing it, as it'll allow you to avoid allocating memory on the heap and dealing with the cleanup of that pointer. In addition, you get to reap the small performance benefit of using member initialization list. However, in both cases you have to face the possibility of the reference to the member variable living longer than the object, which can cause issues.
As for why you were forced to implement operator= and copy constructor, I'm unsure, but unless you declare your constructor as 'explicit', it might want to force you to deal with situations where someone says:
QObject* q = new QObject;
MyClass myObj = q;
As this would cause an implicit conversion.
In C++11, you might be able to delete the operator= and copy constructor instead of defining them though:
MyClass(const MyClass&) = delete;
MyClass& operator=(const MyClass&) = delete;

Is this trick, to make calling shared_from_this() in the constructor 'just work', dangerous?

Question for the C++ experts.
We all know that calling shared_from_this() in the class constructor will result in a bad_weak_ptr exception, because no shared_ptr to the instance has been created yet.
As a work-around for that, I came up with this trick:
class MyClass : public std::enable_shared_from_this<MyClass>
{
public:
MyClass() {}
MyClass( const MyClass& parent )
{
// Create a temporary shared pointer with a null-deleter
// to prevent the instance from being destroyed when it
// goes out of scope:
auto ptr = std::shared_ptr<MyClass>( this, [](MyClass*){} );
// We can now call shared_from_this() in the constructor:
parent->addChild( shared_from_this() );
}
virtual ~MyClass() {}
};
Someone argued that this is not safe, as the object has not yet been fully formed. Is he right about that?
I'm not using 'this' to access member variables or functions. Furthermore, all member variables have already been initialized, provided I used initializer lists. I don't see how this trick could be unsafe.
Edit: it turns out this trick indeed creates unwanted side-effects. The shared_from_this() will point to the temporary shared_ptr and if you're not careful, the parent-child relationship in my sample code will break. The implementation of enable_shared_from_this() simply does not allow it. Thanks, Sehe, for pointing me in the right direction.
That's not dangerous.
The documented restriction is: cppreference
Before calling shared_from_this, there should be at least one std::shared_ptr p that owns
*this
Nowhere does it say that it can't be used from inside the constructor /for this reason/.
It's just a-typical. That's because under normal circumstances, a make_shared or shared_pointer<T>(new T) cannot complete before the T constructor has exited.
Caveat: the object isn't fully formed so you cannot legally invoke any virtual methods (at the penalty of Undefined Behaviour).
Guideline Since it's possible to use this class wrong (e.g. using shared_ptr<T>(new T) which creates a second shared_ptr with the same underlying pointer value... oops) you should prefer a design that prevents this.
Using a friend factory function that returns the shared_ptr<T> could be one approach.
--> See also The Pit Of Success

List of smart pointers - Managing object lifetime and pointer validity

I have a list of smart pointers where each pointer points to a separate Entity class.
std::list<std::unique_ptr<Entity>> m_entities;
I would like the constructor to handle the assigning of each pointer to a std::list class as it is "automatically" handled by the code on class instantiation. However, if this design is bad then I would welcome a better alternative as it only makes sense to me coming from a C# background.
Entity::Entity(Game &game)
: m_game(game),
m_id(m_game.g_idGenerator->generateNewID())
{
m_game.m_entities.push_back(std::unique_ptr<Entity>(this));
}
The main problem I have encountered with this method is that the Entity class' lifetime is unmanaged by the Entity class.
For example if I allocate an Entity class on the stack it will call the Entity destructor after leaving the method in which it was allocated and the pointer will no longer be valid.
I therefore considered the alternative of creating a smart pointer, allocating the Entity class to the heap and then explicitly adding the pointer to the list.
std::unique_ptr<Entity> b(new Entity(*this));
m_entities.push_back(b); // ERROR
This produces the following error
error C2664: 'void std::list<_Ty>::push_back(_Ty &&)' : cannot convert parameter 1 from 'std::unique_ptr<_Ty>' to 'std::unique_ptr<_Ty> &&'
What would be considered the best approach for allocating each pointer to the list and is a constructor based version possible?
I'm currently thinking that it is the list of smart pointers that should handle the lifetime for each Entity class and that assigning pointers in a constructor is not a good design choice. In that case I should probably create a CreateEntity method that adds the pointer to list rather than let the constructor handle it. Is this better?
I considered what type of smart pointer would be appropriate for this operation after reading through questions found here, here and here (offsite). It is difficult to get an exact answer based on what I've read so far though as they all offer somewhat conflicting advice.
Using constructor this way is definitely not good idea because constructor has no information about how object is created and controlled - on the stack, statically, dynamically by some smart pointer, dynamically by dumb pointer?
To solve this problem you could use static factory method to create Entity instances:
class Entity
{
public:
// Variant with unique ownership
static void CreateGameEntity(Game& game)
{
std::unique_ptr<Entity> p(new Entity());
game.m_entities.push_back(std::move(p));
}
// OR (you cannot use both)
// Variant with shared ownership
static std::shared_ptr<Entity> CreateGameEntity(Game& game)
{
std::shared_ptr<Entity> p(new Entity());
game.m_entities.push_back(p);
return p;
}
private:
// Declare ctors private to avoid possibility to create Entity instances
// without CreateGameEntity() method, e.g. on stack.
Entity();
Entity(const Entity&);
};
Which smart pointer to use? Well, this depends on your design. If Game object solely owns Entity instances and completely manages their lifetime, using std::unique_ptr is OK. If you need some kind of shared ownership (e.g. you have several Game objects that can share same Entity objects) you shall use std::shared_ptr.
Also in case of unique ownership you may use Boost Pointer Container library. It contains specialized owning pointer containers like ptr_vector, ptr_list, ptr_map etc.
I won't comment on your design questions, but to fix your error, change your code to either:
m_entities.push_back(std::unique_ptr<Boundary>(new Boundary(*this, body)));
or:
std::unique_ptr<Boundary> b(new Boundary(*this, body));
m_entities.push_back(std::move(b));
The reason is that b in your code is an lvalue, but std::unique_ptr<> is a move-only type (i.e. has no copy constructor).
The problem in your code is that you try to move a std::unique_ptr<T> from an l-value. The instantiations of std::unique_ptr<T> are non-copyable and are only movable. To move from an l-value you need to explicitly do so:
this->m_entities.push_back(std::move(b));
The call to std::move() won't really move anything but it does yield a type which indicates to the compiler that the object can be moved.
To address the issue with the stack-created instance, you could simply add a parameter to the constructor that tells it to not add the new instance to the list, eg:
Entity::Entity(Game &game, bool AddToList = true)
: m_game(game),
m_id(m_game.g_idGenerator->generateNewID())
{
if (AddToList) m_game.m_entities.push_back(this);
}
.
{
...
Entity e(game, false);
...
}
Another option might be to add a destructor to Entity that removes it from the list if it is still present, but that might get a little complex trying to avoid conflicts between direct Entity destructions and unique_ptr destructions.

Must I use pointers for my C++ class fields?

After reading a question on the difference between pointers and references, I decided that I'd like to use references instead of pointers for my class fields. However it seems that this is not possible, because they cannot be declared uninitialized (right?).
In the particular scenario I'm working on right now, I don't want to use normal variables (what's the correct term for them by the way?) because they're automatically initialized when I declare them.
In my snippet, bar1 is automatically instantiated with the default constructor (which isn't what I want), &bar2 causes a compiler error because you can't use uninitialized references (correct?), and *bar3 is happy as larry because pointers can be declared uninitialized (by the way, is it best practice to set this to NULL?).
class Foo
{
public:
Bar bar1;
Bar &bar2;
Bar *bar3;
}
It looks like I have to use pointers in this scenario, is this true? Also, what's the best way of using the variable? The -> syntax is a bit cumbersome... Tough luck? What about smart pointers, etc? Is this relevant?
Update 1:
After attempting to implement a reference variable field in my class and initializing it in the constructor, why might I receive the following error?
../src/textures/VTexture.cpp: In constructor ‘vimrid::textures::VTexture::VTexture()’:
../src/textures/VTexture.cpp:19: error: uninitialized reference member ‘vimrid::textures::VTexture::image’
Here's the real code:
// VTexture.h
class VTexture
{
public:
VTexture(vimrid::imaging::ImageMatrix &rImage);
private:
vimrid::imaging::ImageMatrix ℑ
}
// VTexture.cpp
VTexture::VTexture(ImageMatrix &rImage)
: image(rImage)
{
}
I've also tried doing this in the header, but no luck (I get the same error).
// VTexture.h
class VTexture
{
public:
VTexture(vimrid::imaging::ImageMatrix &rimage) : image(rImage) { }
}
Update 2:
Fred Larson - Yes! There is a default constructor; I neglected it because I thought it wasn't relevant to the problem (how foolish of me). After removing the default constructor I caused a compiler error because the class is used with a std::vector which requires there to be a default constructor. So it looks like I must use a default constructor, and therefore must use a pointer. Shame... or is it? :)
Answer to Question 1:
However it seems that this is not possible, because they [references] cannot be declared uninitialized (right?).
Right.
Answer to Question 2:
In my snippet, bar1 is automatically
instantiated with the default
constructor (which isn't what I want),
&bar2 causes a compiler error because
you can't use uninitialized references
(correct?),
You initialize references of your class in your constructor's initializer list:
class Foo
{
public:
Foo(Bar &rBar) : bar2(rBar), bar3(NULL)
{
}
Bar bar1;
Bar &bar2;
Bar *bar3;
}
Answer to Question 3:
In the particular scenario I'm working
on right now, I don't want to use
normal variables (what's the correct
term for them by the way?)
There is no correct name for them, typically you can just say pointers for most discussions (except this one) and everything you need to discuss will also apply to references. You initialize non pointer, non reference members in the same way via the initailizer list.
class Foo
{
public:
Foo() : x(0), y(4)
{
}
int x, y;
};
Answer to Question 4:
pointers can be declared uninitialized
(by the way, is it best practice to
set this to NULL?).
They can be declared uninitialized yes. It is better to initialize them to NULL because then you can check if they are valid.
int *p = NULL;
//...
//Later in code
if(p)
{
//Do something with p
}
Answer to Question 5:
It looks like I have to use pointers
in this scenario, is this true? Also,
what's the best way of using the
variable?
You can use either pointers or references, but references cannot be re-assigned and references cannot be NULL. A pointer is just like any other variable, like an int, but it holds a memory address. An array is an aliased name for another variable.
A pointer has its own memory address, whereas an array should be seen as sharing the address of the variable it references.
With a reference, after it is initialized and declared, you use it just like you would have used the variable it references. There is no special syntax.
With a pointer, to access the value at the address it holds, you have to dereference the pointer. You do this by putting a * before it.
int x=0;
int *p = &x;//p holds the address of x
int &r(x);//r is a reference to x
//From this point *p == r == x
*p = 3;//change x to 3
r = 4;//change x to 4
//Up until now
int y=0;
p = &y;//p now holds the address of y instead.
Answer to Question 6:
What about smart pointers, etc? Is
this relevant?
Smart pointers (See boost::shared_ptr) are used so that when you allocate on the heap, you do not need to manually free your memory. None of the examples I gave above allocated on the heap. Here is an example where the use of smart pointers would have helped.
void createANewFooAndCallOneOfItsMethods(Bar &bar)
{
Foo *p = new Foo(bar);
p->f();
//The memory for p is never freed here, but if you would have used a smart pointer then it would have been freed here.
}
Answer to Question 7:
Update 1:
After attempting to implement a
reference variable field in my class
and initializing it in the
constructor, why might I receive the
following error?
The problem is that you didn't specify an initializer list. See my answer to question 2 above. Everything after the colon :
class VTexture
{
public:
VTexture(vimrid::imaging::ImageMatrix &rImage)
: image(rImage)
{
}
private:
vimrid::imaging::ImageMatrix ℑ
}
They can be initialized. You just have to use the member initializer list.
Foo::Foo(...) : bar1(...), bar2(...), bar3(...)
{
// Whatever
}
It's a good idea to initialize all of your member variables this way. Otherwise, for other than primitive types, C++ will initialize them with a default constructor anyway. Assigning them within the braces is actually reassigning them, not initializing them.
Also, keep in mind that the member initializer list specifies HOW to initialize the member variables, NOT THE ORDER. Members are initialized in the order in which they are declared, not in the order of the initializers.
Use the null object design pattern
I'm using ints but it would be the same with any type.
//header file
class Foo
{
public:
Foo( void );
Foo( int& i );
private:
int& m_int;
};
//source file
static int s_null_Foo_m_i;
Foo::Foo( void ) :
m_i(s_null_Foo_m_i)
{ }
Foo::Foo( int& i ) :
m_i(i)
{ }
Now you have to make sure that Foo makes sense when default constructed. You can even detect when Foo has been default constructed.
bool Foo::default_constructed( void )
{
return &m_i == &s_null_Foo_m_i;
}
I absolutely agree with the sentiment, Always prefer references over pointers. There are two notable cases where you can't get away with a reference member:
Null has a meaningful value.
This can be avoided with the null object design pattern.
The class has to be assignable.
The compiler will not generate an assignment operator for classes that have a reference member. You can define one yourself, but you will not be able to change where the reference is bound.
There is also a side effect when you define when you define Bar and Bar *
class Foo
{
public:
Bar bar1; // Here, you create a dependency on the definition of Bar, so the header //file for bar always needs to be included.
Bar &bar2;
Bar *bar3; //Here, you create a pointer, and a forward declaration is enough, you don't have to always include the header files for Bar , which is preferred.
}
Using references just because the -> syntax is cumbersome isn't the best reason... References have the one great advatage over pointers in that nulls aren't possible without casting trickery, but also disadvantages in initialization and the risk of accidentally illegaly binding temporaries which then go out of scope (for instance, after an implicit conversion).
Yes, smart pointers such as the boost ones are almost always the right answer for handling composite members, and occasionally for associated members (shared_ptr).
class Foo {
public:
Bar bar1;
Bar &bar2;
Bar *bar3;
// member bar2 must have an initializer in the constructor
Bar::Bar(Bar& _bar2) : bar1(), bar2(_bar2), bar3(new Bar()) {}
Bar::~Bar() {delete bar3;}
}
Note that bar2 isn't just initialized in the ctor; it's initialized with a bar object that's passed in as a reference parameter. That object and the bar2 field will be bound together for the life of the new Foo object. That is usually a very bad idea, because it's hard to ensure that the lifetimes of the two objects will be well coordinated (i.e., that you will never dispose of the passed-in bar object before disposing of the Foo object.)
This is why it's greatly preferred to use either instance variables (as in bar1) or pointers to objects allocated on the heap (as in bar3.)