Home > database >  Move object from local variable to std::shared_ptr
Move object from local variable to std::shared_ptr

Time:03-15

Please note that with the words "object" and "move" in the title, I do not mean the C -specific concepts of what an object is and what it means to move an object.

I have a local variable of a pretty simple struct type where I accumulate some values read from a config file.

struct Foo
{
    std::string name;
    float someValue;
    int someStuff;
};

// This stores the current settings
std::shared_ptr<Foo> currentFooSetting;

void readSettings()
{
    Foo f;
    f.name = ...;
    f.someValue = ...;
    f.someStuff = ...;
    if (everythingIsOk)
    {
        //TODO:
        //Delete the old object pointed to by currentFooSetting (if it's not pointed to by any other shared_ptr, of course)
        //Allocate some new memory to put f into... or maybe reuse *currentFooSetting if it's now free idc.
        //Copy f to the new memory location
        //
    }
}

If everything is OK, I want to move f onto the heap and have currentFooSetting point to that. How do I do that?

It seems I could do this:

std::shared_ptr<Foo> newFooSetting = std::make_shared<Foo>();
*newFooSetting = f;
currentFooSetting = newFooSetting;

(Using a local variable to better emphasize the separation between the allocation, copying, and replacing.) But even after reading through https://en.cppreference.com/w/cpp/memory/shared_ptr and https://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared I have no idea whether that's "the way" of doing this.

CodePudding user response:

It can be done more simply than the attempt in the question:

if (everythingIsOk) {
    currentFooSetting = std::make_shared<Foo>(std::move(f));
}

std::make_shared will allocate dynamic memory and the new object will be initialised by move from f. We could copy too, but in this case the local f is about to go out of scope, so it is safe to move from it.

Assigning currentFooSetting will cause it to destroy the previously pointed object (if any, and if there are no other owners), and currentFooSetting becomes the owner of the newly created object.

CodePudding user response:

How about

if (currentFooSetting) {
    *currentFooSetting = f;
} else {
    currentFooSetting = std::make_shared<Foo>(f);
}

this sort-of ensures that you have just one shared pointer, and once it is created, its value is changed on update. Alternately, if existing holders-of-the-shared-pointer should keep their values, just assign a new one:

currentFooSetting = std::make_shared<Foo>(f);

This will "fork" the views of current settings -- holders-of-a-shared-pointer keep the old one with old values, but functions that newly share the pointer get the new value.

Which makes more sense depends on your design (which is what Ted Lyngmo asks in a comment). Both code snippets assume your Foo class has suitable (copy) constructors.

  • Related