Я бы хотел, чтобы эксперты рассмотрели следующий процесс распределения динамической памяти и предложили, есть ли утечки памяти. Следующий код не является реальным используемым кодом, но пытается понять концепцию распределения памяти и де-распределения по-разному.
class ObjMapData
{
private:
int* itsMapData;
........
public:
ObjMapData();
~ObjMapData(){if(itsMapData!= NULL) delete[] itsMapData;}
ClearMemory() {if(itsMapData!= NULL) {delete[] itsMapData; itsMapData= NULL}}
.......
void SetMapData(int* ptrData) { itsMapData = ptrData;} // or should I use int*&ptrData??
int* GetMapData() const { return itsMapData;}
}
Теперь я могу сделать следующее без утечек памяти?
bool Function1(ObjMapData& objMyMap)
{
//populate the ptrData with some data values using many different ways
int* ptrData = new int[1000]; // usually a variable from binary file header
......................
objMyMap.SetMapData(ptrData);
//don't want to delete the memory yet
return true;
}
bool Function2(ObjMapData& objMyMap)
{
int* ptrData = objMyMap.GetMapData();
//do some work such as writing updated data into a binary file
}
bool Function3(ObjMapData& objMyMap)
{
//populate the data
bool bStatus = Function1(objMyMap);
int* ptrData = objMyMap.GetMapData();
//update the map data using ptrData variable
..........
bStatus = Function2(objMyMap); // write data to a binary file
objMyMap.ClearMemory(); // not real code in use, but for understanding the concept
bStatus = Function1(objMyMap); // re-allocate memory
ptrData = objMyMap.GetMapData();
//update the map data using ptrData variable
objMyMap.SetMapData(ptrData); // Do I need to set again or member pointer get updated automatically?
return true
}
int main()
{
ObjMapData objMyMap;
bool bStatus = Function3(objMyMap);
//default destructor of objMyMap can take care of the allocated memory cleanup
return 0;
}
Спасибо за ваше время, чтобы подтвердить распределение динамической памяти.
Хотя это может показаться более связанным со стилем, чем ваш вопрос об утечках памяти, я бы обрабатывал данные конфиденциально в классе:
class ObjMapData
{
private:
int* itsMapData;
// consider adding 'datasize' member variable
........
public:
ObjMapData(){ itsMapData=NULL; }; // initialise member variable(s)!
~ObjMapData(){ delete[] itsMapData;}
ClearMemory() { delete[] itsMapData; itsMapData=NULL; }
.......
void CreateMapData(int size) { ClearMemory(); itsMapData= new int[size]; }
void FillDataFrom( ???? ) { ???? };
int* GetMapData() const { return itsMapData;}
}
Затем вы можете улучшить класс, добавив конструктор и методы назначения, которые предотвратят утечку памяти при использовании класса.
EDIT Вы спрашиваете:
Мое беспокойство здесь в том, какое из следующего правильно: void SetMapData (int * ptrData) Vs void SetMapData (int * & ptrData)
Оба являются "правильными" в том смысле, что оба разрешают копирование и использование внешнего (для класса) указателя в вашем классе - в отношении "утечек памяти" это зависит от того, какая часть вашего кода вы хотите управлять памятью, которую вы выделены. Ты мог:
Обычно я нахожу, что 1 и 2 имеют больше смысла, чем 3 или 4. т.е. Легче следить за тем, что происходит, с меньшей вероятностью скрывать ошибки и т.д.
Однако, что касается "утечки памяти": не имеет значения, где указатель на выделенный блок памяти, как он был скопирован, назначен или привязан - это значение как важный адрес памяти. Таким образом, до тех пор, пока вы new
и delete
этот адрес памяти, вы не будете просачивать память (независимо от того, находятся ли эти действия внутри класса или нет).
Если в вашем приложении вам нужно выделить/деактивировать массив int, внешний для вашего класса, имеет смысл, что функции-члены ссылаются на указатель как подсказку к читателю о том, что класс не несет ответственности за его освобождение, - но некоторые достойные комментарии должны сделать так ясно :)
За прошедшие годы я столкнулся с множеством ошибок из-за неправильного обращения с "передачей владения" выделенной памяти (более того, с хорошим ol 'C), где был написан какой-то фрагмент кода, предполагающий, что он должен освободить блок или кто-то другой сделает это.
Это ответ на ваш вопрос или я пропустил это?
delete nullptr
безопасно, кстати, вам не нужны проверки на ноль. Вы нарушили правило трех, хотя. Что произойдет, если я скопирую ваш объект? Двойное удаление.