I have something as the following using rapidjson
rapidjson::Value parent;
parent.SetObject();
rapidjson::Value child;
child.SetObject();
parent.AddMember("child", child, document.GetAllocator());
The problem is when I call parent.AddMember(), the library nullifies my child variable because rapidjson uses move semantics.
How can I still keep a reference to the child value when it gets moved?
Ideally, I'd like to keep a reference to the child node so that I can modify it later, without having to go find it in the JSON tree.
Not specific to rapidjson:
When you have a reference to an object child, and the resource owned by child is transferred to another object by moving, the reference to child is still valid, but the referred object is no longer the one that owns the resource.
You cannot make the original reference variable to refer to the other object. But you could use a pointer or a reference wrapper instead, if you change the value of the pointer when the pointed object is moved.
I'm not familiar with rapidjson, but with a brief browsing of documentation, you could at least use parent.FindMember to get a reference to the newly created member, and update the pointer to that.
Related
In the following C++ code, a QML component is created using a QQmlIncubator. The Qt documentation has this snippet from here http://doc.qt.io/qt-5/qqmlincubator.html:
QQmlIncubator incubator;
component->create(incubator);
while (!incubator.isReady()) {
QCoreApplication::processEvents(QEventLoop::AllEvents, 50);
}
// Who owns 'object'? When is it deleted?
QObject *object = incubator.object();
It's my understanding that this snippet isn't totally complete, because you'd need to call delete on component. According to http://doc.qt.io/qt-5/qqmlcomponent.html#create, the QQmlComponent::create() function transfers ownership of the returned object instance to the caller. Good so far.
Now comes my question--who owns object in the snippet above? In my case, I've place the above snippet in a member function of a class, so the QQmlIncubator incubator goes out of scope, and I only hold on to component and object, which are both instance variables of their containing class, and I call delete component in the destructor. Am I cleaning up properly?
So does object belong to component? When does object get destroyed?
Update 1
See my follow-up question: Safely deleting QML component being used in StackView transition.
Short answer
You should destruct the incubated object (if the incubator finished successfully), otherwise a memory leakage occur.
How to manage ownership?
A good approach may be to transfer the ownership to an object parent using QObject::setParent, for example to the visual parent. This is also done by Qt when you construct QML objects in the traditional way:
Any object assigned to an item's data property becomes a child of the
item within its QObject hierarchy, for memory management purposes.
For convenience, the Item data property is its default property.
Reasoning
As mentioned in the QQmlComponent::create(QQmlContext *) documentation, the object ownership is transfered to the user:
The ownership of the returned object instance is transferred to the caller.
So, it is unlikely that the overloaded function QQmlComponent::create(QQmlIncubator &incubator, QQmlContext *context, QQmlContext *forContext) will keep the ownership, although it is not mentioned explicitly in the documentation. One could argue that the ownership is transferred to the QQmlIncubator object. This is indeed the case as long as the component is Loading, once it is ready the ownership is released as (implicitly) documented in QQmlIncubator::clear:
Any in-progress incubation is aborted. If the incubator is in the Ready state, the created object is not deleted.
Note that QQmlIncubator::clear is called inside the destructor of QQmlIncubator.
As currently written in your example, object destruction is currently your responsibility. Most likely you will want to take care of that by calling setParent() on object and thus passing on the responsibility to the parent item.
As you point out about component->create():
The ownership of the returned object instance is transferred to the
caller.
and the incubator gives all appearance of preserving that intention.
An experimental way to verify this would be to check the parent of object as returned from the incubator.
Another way to verify this is to look directly at the relevant source code in Qt. Here are the files for QQmlIncubator:
https://github.com/qt/qtdeclarative/blob/dev/src/qml/qml/qqmlincubator.cpp https://github.com/qt/qtdeclarative/blob/dev/src/qml/qml/qqmlincubator_p.h
https://github.com/qt/qtdeclarative/blob/dev/src/qml/qml/qqmlincubator.h
Examining those files, the only place that result is deleted is in the ::clear method:
if (s == Loading) {
Q_ASSERT(d->compilationUnit);
if (d->result) d->result->deleteLater();
d->result = 0;
}
I'm using box2d and as you already may know, it holds a void* to an object which i can use as reference when collisions occur between different entities. Problem is that the original item is saved inside a shared_ptr since the ownership is unknown and different classes (example player class) can 'equip' another class (weapon).
I'm just wondering if its possible to put this pointer inside a shared_ptr and refer to the same object as the original one?
This is an example:
std::vector<std::shared_ptr<Environment>> listEnvironment;
listEnvironment.push_back(std::make_shared(new Weapon()));
//takes a void pointer
box2d->userId = listEnvironment.back().get();
//some shit happens somewhere else and collision occurs and I get pointer back from box2d's callback:
Environment* envPtr = static_cast<Environment*>(box2d->userId);
As you can see envPtr is going to cause trouble.
Is there a way to refer to the old smart-pointer and increase its reference value?
PS:
In actuality every class creates an box2d body which holds a 'this' pointer so i don't actually have the address to the smart-pointer either. The example above is kind narrowed down to give you a hint of the problem i'm facing.
Best regards
nilo
If Environment has std::enable_shared_from_this<Environment> as a parent class then, yes. Just call envPtr->shared_from_this().
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.
Edit
I suppose the code below would assume I have an overloaded version of addChild() that accepts a Sprite already wrapped in a unique_ptr, where taking ownership would be fine. Just thought I'd mention that before someone else did. :) . I made up all the code here after a very long day, so please take it as pseudo code quality meant only to demonstrate the issue at hand.
Original Question
I'm writing a framework where there is a display list, parents/children etc. I'm thinking that using unique_ptr<Sprite> for example is the way to go here, since when you add a child to a parent display object, it's only logical that the parent now becomes the sole owner of that child.
However, there will be methods available such as getChildAt(index) and getChildByName, etc, which I believe should return a reference or pointer value, since these methods are simply meant to expose a child to operations, not transfer ownership.
Finally, the issue and the reason for this question, is in the following situation. Lets assume we have two Sprite objects which are children of the root of display list, Stage. Let's say we have a third child Sprite.
Stage newStage;
std::unique_ptr<Sprite> parentOne(new Sprite);
std::unique_ptr<Sprite> parentTwo(new Sprite);
newStage.addChild(parentOne); //Stage takes ownership of parentOne
newStage.addChild(parentTwo); //Stage takes ownership of parentTwo
std::unique_ptr<Sprite> someChild(new Sprite);
parentOne->addChild(someChild) //parentOne takes ownership of someChild.
Now, somewhere else lets say in the code base of the game or whatever using this framework, someChild is accessed via getChildAt(int index);.
Sprite& child = parentOne->getChildAt(0);
It would be perfectly legal for the following to then happen.
parentTwo->addChild(child);
The addChild method handles removing the child from it's previous parent, if a parent exists, so that the new parent can now make this child part of its section of the display list.
I'm returning the child(ren) from each sprite as a reference or pointer, because we don't want to hand off ownership (in methods such as getChildAt()), just provide access to the child. We don't want to hand it off as a unique_ptr and have it fall out of scope and die.
However, as I say, it would be perfectly legal and normal for this child (now accessed by a reference or pointer) to be passed off to another container (lets say in a drag and drop operation, dragging an item from one list to another). The problem we have now is that the unique ownership needs to be transferred from one parent to another, but we only have a reference or raw pointer.
I'm wondering what a sane solution to this problem would be. If I return a pointer, is it possible to transfer the ownership correctly at this stage?
void Sprite::addChild(Sprite* newChildToOwn)
{
/* by checking newChildToOwn->parent we can see that the child is already owned
by someone else. We need to not only remove the child from that parents' part of the
display list and add it here, but transfer exclusive object ownership of newChildToOwn
to this->.
*/
}
The release method gets you the pointer to the object and releases it from the unique_ptr
http://en.cppreference.com/w/cpp/memory/unique_ptr/release
For your structure, you should probably have method called releaseChild(index) that handles you the ownership by returning pointer.
To transfer ownership you need to have access to the unique_ptr as the raw pointer knows nothing of how it is being used.
Would it work to have the remove child method return the unique_ptr so that the object is kept alive during the transfer and the Sprite will be able to take the ownership? This will allow references to be used in other places as you have already.
I'm looking at Marmalade's implementation of CSharedPtr, which purports to perform reference counting. The documentation states that:
When the last CSharedPtr<> referring to a particular object goes out of scope, the reference count reaches zero, and the the delete operator is called on the object.
Is there any way to release the object without it going out of scope? I don't seem to be able to set it to NULL.
Try constructing a new CSharedPtr using the constructor that lets you pass in a pointer and then assigning that to the one you want to set to null.
CSharedPtr<T> cNullPtr( NULL );
existingPtr = cNullPtr;