Search code examples
initializationstructureshared-ptrdynamic-memory-allocationinitializer-list

Initialization of dynamically allocated structures using shared pointer


I dont understand why initialization of dynamically allocated structure needs to be done like this (using shared ptr) Just to notify that I am using C++11

If we have struct like this

struct Meme {
   std::string s;
   Meme* p;
}

and later in code, I need to dynamically allocated memory for this structure using shared_ptr, but I need to do instant initialization of structure. Why it is done like this?

std::shared_ptr<Meme> novi=std::make_shared<Meme>(Meme{imena.at(i),nullptr});

part that confuses me is this one :

std::make_shared<Meme>(Meme{imena.at(i),nullptr});

If we set that shared_ptr points to struct Meme, why we need to specify again that initialization list is for struct Meme, by saying

(Meme{imena.at(i),nullptr})

Why this would not work:

std::shared_ptr<Meme> novi=std::make_shared<Meme>({imena.at(i),nullptr});

Is this maybe that initialization list cannot deduct that it should like convert to struct Meme because there is no direct usage of struct Meme(even though make_shared points to struct Meme) ?


Solution

  • make_shared forwards arguments to constructor.

    Make shared_ptr

    Allocates and constructs an object of type T passing args to its constructor, and returns an object of type shared_ptr that owns and stores a pointer to it (with a use count of 1).

    This calls the copy constructor of Meme from new instance you create with Meme{imena.at(i),nullptr}.

    std::shared_ptr<Meme> novi=std::make_shared<Meme>(Meme{imena.at(i),nullptr});
    

    The correct way to construct it with make_shared from forwarded arguments is to create constructor in struct:

    struct Meme {
        std::string s;
        Meme* p;
        Meme(const std::string& s, Meme* p) : s(s), p(p) {}
    };
    
    std::shared_ptr<Meme> novi = std::make_shared<Meme>(imena.at(i),nullptr);
    

    Also you can create an instance with (default) empty constructor and then set its members:

    struct Meme {
        std::string s;
        Meme* p = nullptr;
    };
    
    std::shared_ptr<Meme> novi = std::make_shared<Meme>;
    novi->s = imena.at(i);