Akay
Akay

Reputation: 1132

Safe return and handling of dynamically allocated memory from a function, C++ 11

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.

Upvotes: 0

Views: 534

Answers (2)

Constantinos Glynos
Constantinos Glynos

Reputation: 3186

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

Upvotes: 1

bolov
bolov

Reputation: 75853

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;
};

Upvotes: 1

Related Questions