0

I am new to C++ and thus new to smart pointers concept and usage as well. I want to allocate memory dynamically for a struct in a function and then once the receiver is done using that memory. I want the unique (not shared) receiver to safely release the memory. Something like the following:

typedef struct {
  int x;
  int y;
} myStruct;

myStruct* initMem(void)
{
   myStruct* result = new myStruct();
   result->x = 12;
   result->y = 14;
   return result;
}

int main()
{
  cout << ">>>>> Main | STARTED <<<<<" << endl;
  myStruct* w = initMem();
  cout << w->x << endl;
  cout << w->y << endl;
  delete w;
  return 1;
}

Note: Above is just a sample example of what I want to achieve. The structs are far more complicated than that and I have to use dynamic memory allocations only.

I read that playing with raw pointers in C++ for dynamic memory management is not good as C++ has the concept of smart pointers especially for this. Can you please help me in converting the above logic to using smart pointers.

Thanks in advance.

Akay
  • 1,092
  • 12
  • 32

2 Answers2

1

There is no reason to use pointers and dynamically allocated memory. Use automatic storage duration:

myStruct initMem()
{
   myStruct result{};
   result.x = 12;
   result.y = 14;
   return result;
}

int main()
{
  cout << ">>>>> Main | STARTED <<<<<" << endl;
  myStruct w = initMem();
  cout << w.x << endl;
  cout << w.y << endl;
}

If you have a good reason for using dynamically allocated memory then you must adhere to the RAII principle. Smart pointers in the standard library do just that:

std::unique_ptr<myStruct> initMem(void)
{
   auto result = std::make_unique<myStruct>();
   result->x = 12;
   result->y = 14;
   return result;
}

int main()
{
  std::cout << ">>>>> Main | STARTED <<<<<" << std::endl;
  std::unique_ptr<myStruct> w = initMem();
  std::cout << w->x << std::endl;
  std::cout << w->y << std::endl;
}


Also in C++ you don't need the typedef. Actually it is idiomatic to not use it:

struct myStruct {
  int x;
  int y;
};
bolov
  • 72,283
  • 15
  • 145
  • 224
  • Thanks for the answer, now what if I want to immediately release that memory after the use in main() ? how to achieve that? how to release that memory pointed by that unique pointer, let's say I have some code after that usage and I want to release that memory way before the termination of the main program? – Akay Mar 27 '19 at 12:09
  • 1
    @Akay you can find all the information you want on the documentation for [unqiue_ptr](https://en.cppreference.com/w/cpp/memory/unique_ptr) If you want to release the memory you need to call [reset](https://en.cppreference.com/w/cpp/memory/unique_ptr/reset) or assign `nullptr` to it – bolov Mar 27 '19 at 12:20
  • @Akay see https://stackoverflow.com/questions/7038357/make-unique-and-perfect-forwarding and https://stackoverflow.com/questions/17902405/how-to-implement-make-unique-function-in-c11 – bolov Mar 27 '19 at 13:49
1

Use a unique pointer std::unique_ptr. If coding with c++14 and later, then you can benefit from the std::make_unique which creates a myStruct object and wraps it around a unique pointer.

But even if you don't use c++14 or later, then you can simply create the make_unique function yourself and use it accordingly.

template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args)
{
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

So the following example in c++11 would use make_unique instead of std::make_unique.

#include <iostream>
#include <memory>

struct myStruct
{
    int x;
    int y;

    myStruct(int x_, int y_) : x(x_), y(y_)
    {
        std::cout<< "Calling user-def constructor..." <<std::endl;
    }

    ~myStruct()
    {
        std::cout<< "Calling default destructor..." <<std::endl;
    }
};

int main()
{
    std::cout << ">>>>> Main | STARTED <<<<<" << std::endl;

    std::unique_ptr<myStruct> ptr = std::make_unique<myStruct>(2,3);

    std::cout<< ptr->x << "," << ptr->y <<std::endl;
}

Example online: https://rextester.com/TLIPO27824

Constantinos Glynos
  • 2,952
  • 2
  • 14
  • 32