Using smart pointers as a class member - c++

I have been reading up on smart pointers and recently in class my TA said that we should never use raw pointers. Now, I've done a lot of reading online and looked at different questions on this website but I'm still confused on some aspects of smart pointers. My question is: which smart pointer would I use if I want it to be used across my program? I'll show some code.
So I have a basic Application class that makes declarations of objects from class AI. Note: I have two different smart pointers, a unique one and a shared one, for testing reasons.
// Application class in Application.h
class Application
{
public:
Application(){}
~Application(){}
//... additional non-important variables and such
unique_ptr<AI> *u_AI; // AI object using a unique pointer
shared_ptr<AI> *s_AI; // AI object using a shared pointer
//... additional non-important variables and such
void init();
void update();
};
// AI class in AI.h
class AI
{
public:
AI(){}
~AI(){}
bool isGoingFirst;
};
In the Application init function, I want to create the AI object, and then I want to use it in the update function. I am not sure if I am declaring my pointer right at all, but I know for a fact that it compiles and it works for assigning and printing out data in the init function. More code below.
void Application::init()
{
//.. other initialization's.
std::shared_ptr<AI> temp(new AI());
sh_AI = &temp;
sh_AI->isGoingFirst = true;
//.. other initialization's.
// Function ends.
}
void Application::update()
{
if(sh_AI->get()->isGoingFirst == true)
{
// Do something
}
else
{
// Do something else
}
// Other code below
}
Later in my program, the update function is called, which uses the same AI smart pointer that I declared in my class Application. What I have found out is that the smart pointer AI object is being deleted. I understand that smart pointers have automatic memory management, but is there a smart pointer that will allow you to use a it in different functions without creating any major problems, such as memory leaks or dangling references? Or am I missing the whole point of smart pointers?
I'm sorry if this was answered in another question but I read into a lot of the other questions, and while I understand more about smart pointers, I'm still learning. Thank you!

As Neil Kirk pointed out in the comments, these declarations are not what you want:
unique_ptr<AI> *u_AI; // AI object using a unique pointer
shared_ptr<AI> *s_AI; // AI object using a shared pointer
u_AI and s_AI are still objects to raw pointers. The whole point is to remove the need to manage the raw pointer directly. So now you replace them with:
unique_ptr<AI> u_AI; // AI object using a unique pointer
shared_ptr<AI> s_AI; // AI object using a shared pointer
to assign your created pointer, you use the function make_unique or make_shared:
u_AI = unique_ptr<AI>(new AI()); // Yu may be able to use make_unique like
// make_shared but it's new to C++14. may not be available
s_AI = make_shared<AI>();
Then, when you need to access them, you just pretend they are pointers, so in your update function:
if(sh_AI->get()->isGoingFirst == true)
becomes:
if(sh_AI->isGoingFirst == true)
As for when to use unique_ptr vs shared_ptr, you answer that by answering the following question: What do I want to happen when someone makes a copy of Application? i.e.:
Application app1;
app1.init();
Application app2 = app1; // ?? what happens to AI object in app2?
There are 3 possible answers:
I want there to be an extra copy of AI in app2. In this case you use unique_ptr and make sure you implement a copy constructor that does the copying.
I want app2 and app1 to share a copy of AI. In this case you use shared_ptr and the default copy constructor will do the job for you.
I don't want there ever to be a copy of Application. (Which makes sense for a class called Application). In this case it doesn't really matter (in which case I would default to unique_ptr) and remove the copy constructor:
Application(const Application&) = delete;

Short answer: Since your pointer is public, I suggest you use a shared_ptr. However, your pointer does not need to be public so if it was private you could use a unique_ptr since you only use it in your own instance.
The truth is though that it does not really matter much (and I know I'll get some downvotes with this). There are two reasons to use unique_ptr:
it never leaves your module and you just need a replacement for a naked pointer
you want to explicitly show that it is not supposed to leave your module.
On the other hand if you need to ever share the pointer (even in a read-only way) then you will have to use a shared_ptr.
A lot of times it is more convenient to use shared_ptr to begin with but for reason 2) above it is worth using unique_ptr.
Not a reason to use unique_ptr: performance. All I say is make_shared.
Now to your code
This is how you define a smart pointer:
std::shared_ptr<AI> s_AI;
std::unique_ptr<AI> u_AI;
This is how you initialize it:
s_AI = std::make_shared<AI>(); // or
s_AI = std::shared_ptr<AI>(new AI);
u_AI = std::unique_ptr<AI>(new AI);
Note that there is no std::make_unique in C++11. It's going to be in C++14 and it's not that hard to write a replacement but fact is that in C++11 there is none.
This is how you use the pointers:
s_AI->isGoingFirst;
That's it, it behaves like a normal pointer. Only if you have to pass it to a function that needs a pointer you need to use .get().
here is how you delete (empty) the pointer:
s_AI.reset();
Again, I suggest you make your pointer private. If you need to pass it out make sure you use a shared_ptr and write a getter method:
std::shared_ptr<AI> getAI() const {
return s_AI;
}
Remember that if you do this you can't assume that your AI object will be destroyed when your Application object is.

Related

Getter for large member variables w/o copying

I have a class containing large member variables. In my case, the large member variable is a container of many objects and it must be private as I don't want to allow a user to modify it directly
class Example {
public:
std::vector<BigObject> get_very_big_object() const { return very_big_object; }
private:
std::vector<BigObject> very_big_object;
}
I want a user to be able to view the object without making a copy:
Example e();
auto very_big_object = e.get_very_big_object(); // Uh oh, made a copy
cout << very_big_object[11]; // Look at any element in the vector etc
I'm a bit confused about the best way to do it. I thought about returning a constant reference, i.e., make my getter:
const std::vector<BigObject>& get_very_big_object() const { return very_big_object; }
I read this article that suggests it could be risky and that that a smart pointer std::unique_ptr could be better, but that this problem can be best solved using modern C++11 move semantics. But I found that a bit cryptic.
What's the modern best practice for doing this?
I read this article that suggests it could be risky and that that a smart pointer std::unique_ptr could be better, but that this problem can be best solved using modern C++11 move semantics.
On this point, the article is flat-out wrong. A smart pointer does not remove the "risk".
Quick summary of relevant parts of the article
If a class returns a const reference to a data member, client code may introduce a const_cast and thereby change the data member without going through the class' API.
The article proposes (incorrectly) that the above can be avoided by using a smart pointer. The setup is for the class to maintain a shared pointer to the data, and have the getter return that pointer cast to a shared pointer to const data.
Critique of the points
First of all, this does not work. All one has to do is de-reference the smart pointer to get a const reference to the data, which can then be const_cast as before. Using the author's own example, instead of
std::string &evil = const_cast<std::string&>(obj.someStr());
use
std::string &evil = const_cast<std::string&>(*obj.str_ptr());
to get the same data-changing results when returning a smart pointer. The entire article is not wrong, but it does get several points wrong. This is one of them.
Second of all, this is not your concern. When you return a const reference, you are telling client code that this value is not to be changed. If the client code does so anyway, it's the client code that broke the agreement. Essentially, the client code invoked undefined behavior, so your class is free to do anything, even crash the program.
What's the modern best practice for doing this?
Simply return a const reference. (Most rules have exceptions, but in my experience, this one seems to be on target 95-99.9% of the time.)
What I did when I was working on my BDD-library for school is to create a wrapper class called VeryBigObject, which contacts the singleton upon instantiation and hides a reference-counting pointer, from there you can override the operator->() method to allow for direct access to the class's methods.
So something like this
class VeryBigObject {
private:
vector<BigObject>* obj;
public:
VeryBigObject() {
// find a way to instantiate with a pointer, not by copying
}
VeryBigObject(const VeryBigObject& o) {
// Update reference counts
obj = o.obj;
}
virtual VeryBigObject operator->(const VeryBigObject&); // I don't remember how to do this one, just google it.
... // Do other overloads as you see fit to mask working with the pointer directly.
};
This allows you to create a small portable class that you don't have to worry about copying, but also has access to the larger object easily. You'll still need to worry about things like caching and such though

How do I go about allowing an object of a class type to be uninitialized and identifying when this is the case without using a pointer?

I recently found out for the past few years of me using C++, I have been using pointers far too often and usually when I could easily substitute them for something more appropriate. Something I used them for was using one to allow an object to be uninitialized, and easily check so.
For example, let's say I have a camera that I want to be attaching to an object in a game:
Class Camera {
public:
Entity *attachEntity;
Camera() {
attachEntity = nullptr;
}
void update() {
// If there's an entity to be attached to
if (attachEntity != nullptr) {
...
}
}
};
Is this a bad usage of a pointer? I can't find a good way of doing this without using one. And if it's not supposed to be attached to the entity, you can just set it to nullptr again if it's a pointer. Otherwise, there needs to always be an attachEntity, despite whether or not the camera is attached to it at the moment. Is there anything wrong with this practice? Is there a good way to do this without pointers? I saw that you can't just set an object to NULL like you can a pointer. What's the best way of doing this?
If you want value semantics but still need to be able to omit a
value, you can use std::optional.
You get similar behavior with a std::unique_ptr, except that
the Entity takes up no space when absent but otherwise goes into its
own block of dynamically-allocated memory.
If you want non-owning reference to an Entity instance whose
lifespan will exceed that of the Cameria instance, a raw pointer is
appropriate.
When the Entity is potentially used by multiple Cameras (or other
things) and you need to ensure its lifespan is extended until its
last use, that's where std::shared_ptr fits in.
As Michael pointed out, there's also std::weak_ptr, which is
good to know about but typically rare in practice. It's used to
address a shared_ptr without keeping it alive.
(edited to add #5)
Yes.
Use std::shared_ptr which auto-destructs when no longer needed.
And then you forget everything about copy/move constructors in your classes.
Also it initializes itself to nullptr automatically; No need for your constructor then.
You can also use std::unique_ptr if you are sure that your pointer isn't going to be duplicated, for example, when you only have one object of type Camera. Usually I use shared_ptr to allow copies over threads etc.
Class Camera {
public:
shared_ptr<Entity> attachEntity;
void update() {
// If there's an entity to be attached to
if (attachEntity) {
...
}
}
};
Generally, raw pointers are only nowadays useful to call pointer-only functions, like WinAPI etc. That way, your classes won't need copy/move constructors or assignment operators or destructors, unless you want to move/dup an object which is not visible to the language, like a HANDLE in Windows.
Since you want to attach the camera to one specific entity and change the attachment, you need a pointer.
Since the existence of that entity should be independent of the camera, a raw pointer is appropriate.
If all your entities are shared (as shared_ptrs), a weak_ptr would be best, but it’s not obvious that they should be.
Your solution for the camera is perfectly valid. All the other answers take a long way around of telling you you're doing the right thing by pointing you to shared pointers and optional types, but storing the attach entity as a pointer and using it the way you are is exactly how you would expect it to be done.
I'm going to have some haters, but I personally HIGHLY encourage the use of raw pointers (instead of smart/shared pointers) for real-time applications :).

Initializing shared_ptr member variable, new vs make_shared?

When initializing a shared_ptr member variable:
// .h
class Customer
{
public:
Customer();
private:
std::shared_ptr<OtherClass> something_;
}
// .cpp
Customer():
something_(new OtherClass())
{
}
vs.
Customer():
something_(std::make_shared<OtherClass>())
{
}
Is the make_shared version allowed? I always seem to see the first version, which is preferred?
The only times when make_shared is not allowed are:
If you're getting a naked pointer allocated by someone else and storing it in shared_ptr. This is often the case when interfacing with C APIs.
If the constructor you want to call is not public (make_shared can only call public constructors). This can happen with factory functions, where you want to force users to create the object from the factory.
However, there are ways to get around this. Instead of having a private constructor, have a public constructor. But make the constructor take a type with can only be constructed by those with private access to the class. That way, the only people who can call make_shared with that object type are those with private access to the class.
So yes, you can do this.
In this case, using make_shared is not just allowed, but it is better to use it. If you use new, it will allocate memory for your Customer somewhere and then memory for your shared_ptr somewhere else, storing both strong and weak references (for weak pointers and shared pointers). If you use the make_shared you would have only one place in memory with everything and therefore only one new.
I'm not sure that I was really clear, this was the purpose of the GotW #89, read it, it is well explained there.

Which kind of (auto) pointer to use?

I came accross several questions where answers state that using T* is never the best idea.
While I already make much use of RIIC, there is one particular point in my code, where I use T*. Reading about several auto-pointers, I couldn't find one where I'd say that I have a clear advantage from using it.
My scenario:
class MyClass
{
...
// This map is huge and only used by MyClass and
// and several objects that are only used by MyClass as well.
HashMap<string, Id> _hugeIdMap;
...
void doSomething()
{
MyMapper mapper;
// Here is what I pass. The reason I can't pass a const-ref is
// that the mapper may possibly assign new IDs for keys not yet in the map.
mapper.setIdMap(&_hugeIdMap);
mapper.map(...);
}
}
MyMapper now has a HashMap<...>* member, which - according to highly voted answers in questions on unrelated problems - never is a good idea (Altough the mapper will go out of scope before the instance of MyClass does and hence I do not consider it too much of a problem. There's no new in the mapper and no delete will be needed).
So what is the best alternative in this particular use-case?
Personally I think a raw pointer (or reference) is okay here. Smart pointers are concerned with managing the lifetime of the object pointed to, and in this case MyMapper isn't managing the lifetime of that object, MyClass is. You also shouldn't have a smart pointer pointing to an object that was not dynamically allocated (which the hash map isn't in this case).
Personally, I'd use something like the following:
class MyMapper
{
public:
MyMapper(HashMap<string, Id> &map)
: _map(map)
{
}
private:
HashMap<string, Id> &_map
};
Note that this will prevent MyMapper from having an assignment operator, and it can only work if it's acceptable to pass the HashMap in the constructor; if that is a problem, I'd make the member a pointer (though I'd still pass the argument as a reference, and do _map(&map) in the initializer list).
If it's possible for MyMapper or any other class using the hash map to outlive MyClass, then you'd have to start thinking about smart pointers. In that case, I would probably recommend std::shared_ptr, but you'd have to use it everywhere: _hugeIdMap would have to be a shared_ptr to a dynamically allocated value, not a regular non-pointer field.
Update:
Since you said that using a reference is not acceptable due to the project's coding standards, I would suggest just sticking with a raw pointer for the reasons mentioned above.
Naked pointers (normally referred to as raw pointers) are just fine when the object has no responsibility to delete the object. In the case of MyMapper then the pointer points to an object already owned by MyClass and is therefore absolutely fine to not delete it. The problem arises when you use raw pointers when you do intend for objects to be deleted through them, which is where problems lie. People only ask questions when they have problems, which is why you almost always see it only used in a problematic context, but raw pointers in a non-owning context is fine.
How about passing it into the constructor and keeping a reference (or const-reference) to it? That way your intent of not owning the object is made clear.
Passing auto-pointers or shared-pointers are mostly for communicating ownership.
shared pointers indicate it's shared
auto-pointers indicate it's the receivers responsibility
references indicate it's the senders responsibility
blank pointers indicate nothing.
About your coding style:
our coding standards have a convention that says never pass non-const references.
Whether you use the C++ reference mechanism or the C++ pointer mechanism, you're passing a (English-meaning) reference to the internal storage that will change. I think your coding standard is trying to tell you not to do that at all, not so much that you can't use references to do so but that you can do it in another way.

AddRef and function signature

I've always used the following rule for signatures of functions that return ref-counted objects based on whether they do an AddRef or not, but want to explain it to my colleagues too... So my question is, is the rule described below a widely followed rule? I'm looking for pointers to (for example) coding rules that advocate this style.
If the function does not add a reference to the object, it should be returned as the return value of the function:
class MyClass
{
protected:
IUnknown *getObj() { return m_obj; }
private:
IUnknown *m_obj;
};
However, if the function adds a reference to the object, then a pointer-to-pointer of the object is passed as a parameter to the function:
class MyClass
{
public:
void getObj(IUnknown **outObj) { *outObj = m_obj; (*outObj)->AddRef(); }
private:
IUnknown *m_obj;
};
It's much more typical to use the reference-counting smart pointers for cases when a new object is created and the caller has to take ownership of it.
I've used this same style on projects with a lot of COM. It was taught to me by a couple of people that learned it when they worked at NuMega on a little thing called SoftICE. I think this is also the style taught in the book "Essential COM", by Don Box (here it is at Amazon). At one point in time this book was considered the Bible for COM. I think the only reason this isn't still the case is that COM has become so much more than just COM.
All that said, I prefer CComPtr and other smart pointers.
One approach is to never use the function's return value. Only use output parameters, as in your second case. This is already a rule anyway in published COM interfaces.
Here's an "official" reference but, as is typical, it doesn't even mention your first case: http://support.microsoft.com/kb/104138
But inside a component, banning return values makes for ugly code. It is much nicer to have composability - i.e. putting functions together conveniently, passing the return value of one function directly as an argument to another.
Smart pointers allow you to do that. They are banned in public COM interfaces but then so are non-HRESULT return values. Consequently, your problem goes away. If you want to use a return value to pass back an interface pointer, do it via a smart pointer. And store members in smart pointers as well.
However, suppose for some reason you didn't want to use smart pointers (you're crazy, by the way!) then I can tell you that your reasoning is correct. Your function is acting as a "property getter", and in your first example it should not AddRef.
So your rule is correct (although there's a bug in your implementation which I'll come to in a second, as you may not have spotted it.)
This function wants an object:
void Foo(IUnknown *obj);
It doesn't need to affect obj's refcount at all, unless it wants to store it in a member variable. It certainly should NOT be the responsibility of Foo to call Release on obj before it returns! Imagine the mess that would create.
Now this function returns an object:
IUnknown *Bar();
And very often we like to compose functions, passing the output of one directly to another:
Foo(Bar());
This would not work if Bar had bumped up the refcount of whatever it returned. Who's going to Release it? So Bar does not call AddRef. This means that it is returning something that it stores and manages, i.e. it's effectively a property getter.
Also if the caller is using a smart pointer, p:
p = Bar();
Any sane smart pointer is going to AddRef when it is assigned an object. If Bar had also AddRef-ed well, we have again leaked one count. This is really just a special case of the same composability problem.
Output parameters (pointer-to-pointer) are different, because they aren't affected by the composability problem in the same way:
Again, smart pointers provide the most common case, using your second example:
myClass.getObj(&p);
The smart pointer isn't going to do any ref-counting here, so getObj has to do it.
Now we come to the bug. Suppose smart pointer p already points to something when you pass it to getObj...
The corrected version is:
void getObj(IUnknown **outObj)
{
if (*outObj != 0)
(*outObj)->Release();
*outObj = m_obj;
(*outObj)->AddRef(); // might want to check for 0 here also
}
In practise, people make that mistake so often that I find it simpler to make my smart pointer assert if operator& is called when it already has an object.