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.
Related
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.
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
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.
In my game there are a lot of object of class Foo that interact with each other. A static method of the class Foo update all the object, using a container in order to track the created objects.
My problem is that a Foo object could kill another object, other instances of Foo don't know about this horrible event and they could use the dead object (deleted) anyway, thus giving an error.
I have some ideas to avoid pointer to deleted object, but I don't think they are suitable.
1) A kind of smart pointer that checks for null object.
probably this is the worse idea, I didn't not see anywhere something like this. I could create a pointer which, when delete is called, delete the pointed Foo object and then gives false when converted to Boolean (so it's possible to know if it's possible to call method on it).
2) Each Foo object doesn't track other object with a pointer but with an ID.
then the object gets a pointer to another Foo object with a static method of Foo class ( as I said Foo class has a container that tracks all the instances).
It would work also in a multithreaded environment with simple modifications, but it may be really expansive, each object searches another one in the container during each frame.
3) Each Foo object tracks objects that have a pointer to it.
The object, when killed (deleted), calls a method of the other objects. Then these object erase any pointer to the deleted object. There are other classes, too. So this isn't really object oriented.
I actually think there is an easy solution that I can't find.
Essentially all these objects share ownership of this killable object. The strongest assurance you can give them is that it won't be deleted out from under them. You can accomplish that by giving each one a boost::shared_ptr. Notifying all the objects when it dies would allow them to drop their reference. You can use boost::signals to accomplish that. I would try for this first.
If you can't do that, then you could have them store a boost::weak_ptr and when their call to boost::weak_ptr::lock failed, they would know it was dead.
I have two four classes:
MainClass (class where things start)
XmlReader (class used to parse an xml file)
SerialPortSettings (holds info about the serial port read from the xml-file, e.g. baud rate, comport etc)
SerialPortListener (takes a reference to a SerialPortSettings object in its constructor)
MainClass has a method to read things from an xml-file.
In this method, it first creates an instance of XmlReader and gives it an xml-file as a constructor parameter. This xmlReader does only need to exist within this method:
XmlReader xmlReader (xmlFile);
The xmlReader parsers the xmlFile. MainClass gets access the xml-stuff by calling get-methods in XmlReader. So far everything is good.
However, one of the methods XmlReader offers, is a method which creates an object of type SerialPortSettings based on the information read from the xml-file:
SerialPortSettings* XmlReader::getSerialPortSettings() {
.... // reading stuff from xml file
return new SerialPortSettings(baudRate, dataBits, comport);
}
This method is called from MainClass and the return value is stored in a pointer:
SerialPortSettings* settings = xmlReader.getSerialPortSettings();
The next thing the MainClass does is to create a SerialPortListener (which is a member-variable that has to exist until MainClass is exited). SerialPortListener takes a reference to a SerialPortSettings in it's constructor:
m_serialPortListener = new SerialPortListener(*settings);
Hence SerialPortSettings also has to exist until MainClass exits, therefore I have created this as a pointer.
So here is the clue:
In the SerialPortListener destructor I tried to delete the SerialPortSettings-object:
SerialPortListener::~SerialPortListener() {
delete &m_settings;
}
Then in the MainClass destructor I deleted the SerialPortListener-object:
MainClass::~MainClass() {
delete m_serialPortListener;
}
This fails. I get an error saying that I deleted something twice in the main-class:
*** glibc detected *** ./ioserver: double free or corruption (out): 0x00860d80 ***
When I remove the delete &m_settings from SerialPortListener, it works fine.
But when should pointer be deleted? What is the correct thing to do? I really want my xml-reader to create the SerialPortSettings - object, insted of returning all of the info (baud rate, comport etc) to MainClass and create the SerialPortSettings object itself.
A good solution is to simply let xmlReader::getSerialPortSettings return a SerialPortSettings by value.
Let the compiler do the optimization.
But where you do need to handle pointer lifetimes, do use smart pointers, such as std::auto_ptr or boost::shared_ptr. The key idea is to define ownership. The owner (which in the case of boost::shared_ptr is the collection of smart pointers referring to the object) is responsible for deleting – no-one else.
Cheers & hth.,
The pointer should be deleted at the end of MainClass.
It makes no sense (to me, at least) to use delete on a reference.
It would be way cleaner to not have the XML reader create new objects; treat SerialPortSettings as a "dumb" container, and just pass in a reference to fill in with data from the XML:
XmlReader::getSerialPortSettings(SerialPortSettings& settings);
the actual instance can then be a local variable in the main program, and be passed (by const reference, this time) to the serial port when it's created:
SerialPortSettings portSettings;
m_xmlReader->getSerialPortSettings(portSettings);
m_serialPort = new SerialPort(portSettings);
the life time of the settings instance is then naturally the same as the scope it's in, since it's just a local variable.
If the method in the main class that reads XML needs to exit before the serial port goes out of scope, you could make the settings a member variable of the main class, instead.
What is the datatype of m_settings? Is it a SerialPortSettings* or a SerialPortSettings? If the latter, you can't delete it like that anyway, as it's allocated on the stack. If it's the former (a pointer), you do not need the reference operator. Simply write delete m_settings;
A simple typo in your delete:
delete &m_settings;
should be:
delete m_settings;
For any pointer you should decide who owns the pointer, and that should be who deletes it.
Or you can use a smart pointer such as shared_ptr and eliminate the problem altogether.
SerialPortListener::~SerialPortListener() {
delete &m_settings;
}
That block looks quite weird. Are you sure you aren't trying to delete value by reference? Cause C++ does it automatically when you delete the class, so your delete is really trying to delete twice.
OK, first of all, you're missing the truly important bit of information which is HOW is SerialPortListener::m_settings being stored. Because of the error you're getting, I'm guessing you're actually storing a copy of it, which means: I bet you have something like this:
class SerialPortListener {
SerialPortSettings m_settings;
SerialPortListener(SerialPortSettings set) {
m_settings = set;
}
}
if it's something similar to this, then the listener is saving a copy of the object in it's own memory, and deleting it doesn't make sense, since it's not a pointer. Rule of thumb, never do delete &anything until you know what you're doing and realize you really need to.
In terms of "correctness", the pointer should be freed by the main class, since it was who created it. Or if you don't have any use for it in the main class, and want the listener to delete it, save a pointer instead of an object or reference in the listener.
I ended up making m_serialPortSettings a pointer in SerialPortListener, and deleting it from there.