Search code examples
c++c++17shared-ptrsmart-pointers

Move object from local variable to std::shared_ptr


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.


Solution

  • 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.