Exception safety C++ shared pointer - c++

I try to implement a JSON framework in C++ and want to make use of polymorphic concepts. I have a class JSONNode which is kind of container that stores other JSONNode objects itself and so on. I am doing this with pointers and dynamic allocation. For exception safety I do not want to use new/delete but go with boost shared pointer. A basic scenario for adding an element (a further json object) to a json object looks like this:
typedef boost::shared_ptr<JSONNode> JSONNodePtr;
void JSONNode::Add(JSONNodePtr nodePtr, const std::string& name)
{
this->elements[name] = nodePtr; // store in STL std::map
}
// create and add json object
JSONNodePtr obj(new JSONNode());
JSONNodePtr element(new JSONNode());
obj->Add(element, "firstElement");
For easier use I would rather do it without explicit allocation of element and put the creation of the shared pointer into the class method Add:
void JSONNode::Add(JSONNode* node, const std::string& name)
{
JSONNodePtr nodePtr(node);
this->elements[name] = nodePtr;
}
// create and add json object
...
obj->Add(new JSONNode, "firstElement");
But is that still exception safe? I guess not because the creation of the shared pointer is not immediately done with the allocation of the JSONNode*. What do you think? Or are there other more common ways to implement this?

But is that still exception safe?
No. If the construction of the string to pass as the other argument to Add throws, then the dynamic object may be leaked. It is unspecified which argument is created first.
The original code ensures that the dynamic object is assigned to a smart pointer before anything else happens: the only thing that could fail is the creation of the smart pointer itself, in which case it will delete the object.
Or are there other more common ways to implement this?
It's generally a better idea to use the make_shared function template, rather than using new yourself. Not only does it guarantee exception safety by never exposing a naked pointer, it also makes more efficient use of memory by creating the controlled object and the shared reference count in a single block of memory.
obj->Add(boost::make_shared<JSONNode>(), "firstElement"); // or std:: in C++11

Related

Object creates another instance instead of modifying the one that's pointed

In my main I have variables:
ProcessManager mng;
MemoryManager mem;
dysk disk;
and I'm trying to use these pointers (also in main)
std::shared_ptr<MemoryManager> wsk= std::make_shared<MemoryManager>(mem) ;
std::shared_ptr<dysk> wsk_d = std::make_shared<dysk>(disk);
to pass these objects to an instance of my antoher object (through constructor:
Interpreter interpreter(wsk,wsk_d);
but it looks like intepreter creates his own instance of disk, why?
class Interpreter
{
private:
std::shared_ptr<PCB> pcb;
std::shared_ptr<MemoryManager> mm;
std::shared_ptr<dysk> disk;
}
That's what std::make_shared does: Create a new object using the passed arguments to pass to a suitable constructor. In your case a copy-constructor.
That is, the statement
std::shared_ptr<MemoryManager> wsk= std::make_shared<MemoryManager>(mem);
is equivalent to
std::shared_ptr<MemoryManager> wsk(new MemoryManager(mem));
If you want to have your shared pointer reference the existing object then you need to use e.g.
std::shared_ptr<MemoryManager> wsk(&mem);
But that will bring with it other problems since when the last shared pointer is destructed then it will attempt to free the memory, which is not possible for object not created by new. There are two solutions to this: Either creating a (or using an existing) null-deleter which doesn't actually delete anything; Or by letting the shared pointer handle the complete ownership (from creation to destruction) of the object.
And that's really how you should look at the smart pointers, not as a kind of self-deleting pointer, but in terms of resource ownership.

Using smart pointers as a class member

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.

How to properly use shared_ptr in good C++ APIs

I'm currently trying to find out how to properly use the shared_ptr feature of C++11 in C++ APIs. The main area where I need it is in container classes (Like nodes in a scene graph for example which may contain a list of child nodes and a reference to the parent node and stuff like that). Creating copies of the nodes is not an option and using references or pointers is pain in the ass because no one really knows who is responsible for destructing the nodes (And when someone destructs a node which is still referenced by some other node the program will crash).
So I think using shared_ptr may be a good idea here. Let's take a look at the following simplified example (Which demonstrates a child node which must be connected to a parent node):
#include <memory>
#include <iostream>
using namespace std;
class Parent {};
class Child {
private:
shared_ptr<Parent> parent;
public:
Child(const shared_ptr<Parent>& parent) : parent(parent) {}
Parent& getParent() { return *parent.get(); }
};
int main() {
// Create parent
shared_ptr<Parent> parent(new Parent());
// Create child for the parent
Child child(parent);
// Some other code may need to get the parent from the child again like this:
Parent& p = child.getParent();
...
return 0;
}
This API forces the user to use a shared_ptr for creating the actual connection between the child and the parent. But in other methods I want a more simple API, that's why the getParent() method returns a reference to the parent and not the shared_ptr.
My first question is: Is this a correct usage of shared_ptr? Or is there room for improvement?
My second question is: How do I properly react on null-pointers? Because the getParent method returns a reference the user may think it never can return NULL. But that's wrong because it will return NULL when someone passes a shared pointer containing a null-pointer to the constructor. Actually I don't want null pointers. The parent must always be set. How do I properly handle this? By manually checking the shared pointer in the constructor and throwing an exception when it contains NULL? Or is there a better way? Maybe some sort of non-nullable-shared-pointer?
Using shared pointers for the purpose you describe is reasonable and increasingly common in C++11 libraries.
A few points to note:
On an API, taking a shared_ptr as an argument forces the caller construct a shared_ptr. This is definitely a good move where there is a transfer of ownership of the pointee. In cases where the function merely uses a shared_ptr, it may be acceptable to take a reference to the object or the shared_ptr
You are using shared_ptr<Parent> to hold a back reference to the parent object whilst using one in the other direction. This will create a retain-cycle resulting in objects that never get deleted. In general, used a shared_ptr when referencing from the top down, and a weak_ptr when referencing up. Watch out in particular for delegate/callback/observer objects - these almost always want a weak_ptr to the callee. You also need to take care around lambdas if they are executing asynchronously. A common pattern is to capture a weak_ptr.
Passing shared pointers by reference rather than value is a stylistic point with arguments for and against. Clearly when passing by reference you are not passing ownership (e.g. increasing the reference count on the object). On the other hand, you are also not taking the overhead either. There is a danger that you under reference objects this way. On a more practical level, with a C++11 compiler and standard library, passing by value should result in a move rather than copy construction and be very nearly free anyway. However, passing by reference makes debugging considerably easier as you won't be repeatedly stepping into shared_ptr's constructor.
Construct your shared_ptr with std::make_shared rather than new() and shared_ptr's constructor
shared_ptr<Parent> parent = std::make_shared<Parent>();
With modern compilers and libraries this can save a call to new().
both shared_ptr and weak_ptr can contain NULL - just as any other pointer can. You should always get in the habit of checking before dereferencing and probably assert()ing liberally too. For the constructor case, you can always accept NULL pointers and instead throw at the point of use.
You might consider using a typedef for your shared pointer type. One style that is sometimes used is follows:
typedef std::weak_ptr<Parent> Parent_P;
typedef std::shared_ptr<Parent> Parent_WkP;
typedef std::weak_ptr<Child> Child_P;
typedef std::shared_ptr<Child> Child_WkP;
It's also useful to know that in header files you can forward declare shared_ptr<Type> without having seen a full declaration for Type. This can save a lot of header bloat
The way that you are using shared pointers is correct with 2 caveats.
That your tree of parents and childen must share the lifetime of the pointers with other objects. If your Parent child tree will be the sole users of the pointer, please use a unique_ptr. If another object controls the lifetime of the pointer are you only want to reference the pointer, you may be better off using a weak_ptr unless the lifetime is guaranteed to exceed your Parent Child tree the raw pointer may be suitable.. Please remember that with shared_ptr you can get circular reference so it is not a silver bullet.
As for how to control NULL pointers: well this all comes down to the contract implicit in your API. If the user is not allowed to supply a null pointer, you just need to document this fact. The best way to do this is to include an assert that the pointer is not null. This will crash your application in debug mode (if the pointer is null) but will not incur a runtime penalty on your release binary. If however a null pointer is is an allowed input for some reason, then you need to provide correct error handling in the case of a null pointer.
Children do not own their parents. Rather, it's the other way around. If children need to be able to get their parents, then use a non-owning pointer or reference. Use shared (or better, unique if you can) pointer for parent to child.

QSharedPointer, how to pass them around, and do I need them?

Been trying to understand shared pointer for a few days now and it feels like I cant seem to get it. Not sure if it's just to obvious or if it's too complicated. First of all, could anyone please give me an example where you would ACTUALLY use shared pointers. The examples on Wikipedia makes no sense to me. And how would you pass a shared pointer to another function or create an object with a shared pointer. So, how do you pass it around and where would you use it? ANY information or examples would be great.
Also, I have this issue where I don't know what to use. I have this function where I allocate a QFile and passes it to a function in another class. That function takes the file as a QIODevice* and then creates an object containing the file. I was wondering what the best solution would be here and how (if I should) use a shared pointer here? How can I make a shared pointer with <QFile> and pass it in where the function takes <QIODevice>. Feels like I don't get shared pointers at all...
My other approach would be to put the allocation of the QFile in a QScopedPointer. I then pass it to the class and when creating the object where the file will be stored, I use QPointer or QScopedPointer. In the end of the first calling function I should call take() right?
function () {
QScopedPointer<QFile> item(new QFile("filename"));
SomeClassObject->doStuff(item.data());
item.take();
}
---------------------------------
SomeClass::doStuff(QIODevice *item) {
_currentObject = new MyObject(item); // should _currentObject be a smartpointer?
...
}
---------------------------------
class MyObject {
QPointer<QIODevice> _item;
...
MyObject(QIODevice *item) { _item = item; }
}
So I want a way to store pointers and a way to handle them during creation if "new" throws an exception.
The point of shared pointers (and other similar wrappers for pointers) is to handle destruction of the pointer-to object properly. That is instead of having to manually make sure you delete the last copy (and only the last copy), the shared pointer takes care of it for you when it goes out of scope. The shared part means that you can create copies of this wrapper object (the shared pointer object) and it will "share" the pointer-to object between the copies (just as if you made a copy of a regular pointer) with the added benefit described above.
As for your code, SomeClass::doStuff() should have a QScopedPointer<QFile> parameter (instead of a QIODevice* one) as you are passing item to it, which has that type.
Same with MyObject's constructor: have it take a parameter of QPointer<QIODevice> or QSharedPointer<QIODevice> type. In general, everywhere where you would use pointers, use QSharedPointer instead (with the appropriate template type). This will save you from headaches related to accessing deleted objects later on.
Of course, sometimes you actually need the raw QIODevice pointer (e.g. for third-party library call), then you would use the data() member function of the shared pointer object. Just make sure you do not persist (that is store or otherwise copy beyond what's necessary) the returned raw pointer, because that will undercut the purpose of the shared pointers -- the shared pointers will not know about your extra raw pointer that is not under the management of the shared pointer objects.
EDIT:
take() releases the ownership of the pointed-to object from a scoped pointer, so when the scoped pointer is destroyed, it does not delete the object. You would ant ot use it in a situation when you transfered ownership to somthing else -- like in your case to MyObject.

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.