Безопасный возврат и обработка динамически выделенной памяти из функции, C ++ 11 - PullRequest
0 голосов
/ 26 марта 2019

Я новичок в C ++ и, следовательно, плохо знаком с концепцией и использованием интеллектуальных указателей.Я хочу динамически распределять память для структуры в функции, а затем, как только получатель завершит работу с этой памятью.Я хочу, чтобы уникальный (не общий) приемник безопасно освободил память.Примерно так:

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

Примечание. Выше приведен лишь пример того, чего я хочу достичь.Структуры намного сложнее, и я должен использовать только динамическое выделение памяти.

Я читал, что играть с необработанными указателями в C ++ для динамического управления памятью не очень хорошо, поскольку в C ++ есть концепция интеллектуальных указателей, особенно дляэтот.Не могли бы вы помочь мне в преобразовании вышеупомянутой логики в использование умных указателей.

Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 26 марта 2019

Использовать уникальный указатель std::unique_ptr. При кодировании с использованием c ++ 14 и более поздних версий вы можете воспользоваться std::make_unique, который создает объект myStruct и оборачивает его вокруг уникального указателя.

Но даже если вы не используете c ++ 14 или новее, вы можете просто создать функцию make_unique и использовать ее соответствующим образом.

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

Так что в следующем примере в c ++ 11 вместо std::make_unique будет использоваться 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;
}

Пример онлайн: https://rextester.com/TLIPO27824

1 голос
/ 26 марта 2019

Нет причин использовать указатели и динамически распределенную память. Использовать автоматическое время хранения:

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

Если у вас есть веские основания для использования динамически выделяемой памяти, вы должны придерживаться принципа RAII. Умные указатели в стандартной библиотеке делают именно это:

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


Также в C ++ вам не нужен typedef. На самом деле идиоматично не использовать его:

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