Управление динамической памятью в С++

212
11 декабря 2018, 04:20

Подскажите есть ли правила хорошего тона или общепринятые соглашения по управлению динамической памятью в C++.

Например есть класс

class SomeData {
private:
  char* internalString_;
public:
          SomeData(char * internalString);
}

Как правильно реализовать конструктор? Класс должен сам выделить память и скопировать в нее строку?

SomeData::SomeData( char* internalString ) {
    internalString_ = new char[strlen(internalString)+1];
    *internalString_ = '\0';
    strcpy( internalString_, internalString);
}

Или можно оставить выделение памяти за тем кто вызывает конструктор? Вот так:

SomeData::SomeData( char* internalString ) {
    internalString_ = internalString;
}

И что делать если это будет не строка а более сложный объект, которые еще как то инициализировать необходимо?

Если можно и так и так, то в каких случаях какой политики придерживаться?

Answer 1

Смотрите - если выделяет кто-то другой, то кто должен освобождать память? Если деструктор - то вы не защищены от того, чтоб не передать случайно адрес массива. Если самостоятельно - надо отслеживать, что все объекты уже уничтожены, и не забыть освободить.

Поэтому в общем случае (исключения, подтверждающие правило, всегда возможны) используется идиома RAII - захват ресурса есть инициализация (а деструкция - освобождение).

Так что в общем случае забирайте ресурсы в конструкторе, а освобождайте в деструкторе.

Answer 2

В общем, если у вас в классе есть указатель или ссылька, то в обязательном порядке определите деструктор(освобождать память), конструктор копирования(копировать не указатель, а обьект, на который указывает он), оператор присваивания(присвоить указатель или обьект?...)... Если хотите придерживаться правилам хорошего тона. И ваш класс как минимум будет выглядеть так:

class SomeData {
private:
  char* internalString_;
public:
          SomeData(char * internalString);
          SomeData(const SomeData&);
          SomeData& operator =(const SomeData&);
          ~SomeData() { delete [] internalString_; }
};

А вот в первом определении вашего конструктора наблюдаю ошибку:

*internalString_ = '\0';  

Зачем первому сиволу присваивать символ конца строки?... Просто убрать эту строку

А еще лучше вместо указателей хранить умный указатель, или, для вашего случая, обьект std::string, тогда не нужно будет заморачиваться с копированием и уничтожением

READ ALSO
Передается указатель вместо копии

Передается указатель вместо копии

Почему адрес objects у form, user,user2,user3 одинаковый? И как это исправить?

198
C++ WinApi WNDPROC в классе

C++ WinApi WNDPROC в классе

Как поместить WndProc в класс? Как это работает в оконных библиотеках? (например GLFW)Как я понял в windows forms все события это wndproc, но как wndproc помещен...

172
Как в cmake производит поиск библиотек в Windows?

Как в cmake производит поиск библиотек в Windows?

Пишу небольшой кроссплатформенный проект на qt5 + cmake с использованием protobufНа linux всё собирается замечательно но на windows cmake не может выполнит...

183
Инструкция по запуску Tensorflow на opencv

Инструкция по запуску Tensorflow на opencv

Обучили модель tensorflow 15

143