Глупо ли иметь указатель в качестве поля члена в классе C++?
Я хочу проверить, правильно ли я понимаю. Если бы у меня было следующее в моем заголовке:
public Obj * objPtr;
и следующее в классе:
void create() {
//create a local variable object
Obj localVar = object();
objPtr = &localVar;
}
void edit(){
//attempt to edit value of member pointer
objPtr->edit();
}
Правильно ли я считаю, что это никогда не сработает? Поскольку localVar является локальным, он будет уничтожен один раз за пределами функции create, в результате чего objPtr будет иметь адрес пустой памяти, что означает, что objPtr является нулевым указателем?
во-вторых, сработало бы, если бы я это сделал:Obj localVar = new object()
или же objPtr = new object()
3 ответа
Правильно ли я считаю, что это никогда не сработает?
Только частично. Вам может повезти, и это может сработать, но поведение, как ожидается, будет непредсказуемым (или, точнее, неопределенным) и определенно будет ошибкой в коде.
Причина в том, что контент может присутствовать или не присутствовать по указанному адресу. Точка, в которой память используется для create
Прежний стековый фрейм повторно используется системой, зависит от нескольких факторов, в том числе от того, что программа пытается делать дальше (например, немедленно вызвать другую функцию, "объявить больше переменных") и специфичный для архитектуры код, который генерируется компилятором для нее.
Если программа решает сделать что-то, что заставляет ее изменить прежний кадр стека create
функция (например, вызов другой функции), тогда вы в конечном итоге с неопределенным поведением, если вы попытаетесь использовать указатель на &localVar
,
так как localVar локальный, он будет уничтожен один раз за пределами функции create, оставляя objPtr адрес пустой памяти
Это не будет "пустой" памятью. Сказать, что это неверный адрес, может быть более точным здесь. Если вам повезет, у вас останется прежнее значение (чем больше вы ждете, тем меньше вероятность, что вам повезет). Не повезло, и вы получите мусор. По- настоящему не повезло, и вы получаете что-то, что относится к чему-то другому (например, к какой-то другой переменной) и может испортить вещи или вызвать ошибку сегментации.
что означает, что objPtr является нулевым указателем?
Нулевой указатель - это когда адрес равен нулю, т.е. char *ptr = 0; // same as NULL
,
во-вторых, будет ли это работать, если я сделаю это: Obj localVar = new object() или objPtr = new object()
Код выше не будет работать. Вы должны использовать указатели, но localVar
не один
Если вы напишите что-то вроде:
Obj *my_function() {
Obj *ptrObj = new Obj(); // notice it's a pointer
// ...
return ptrObj;
}
Тогда да, это будет работать. Но вы должны понимать, почему есть разница.
В первом случае вы помещаете содержимое в стек, который получает pop
Ed после возврата функции вместе с Obj
сам. Во втором случае это работает, потому что единственное, что находится в стеке, это указатель на Obj
, но Obj
Сам экземпляр находится в куче, которая выживает после очистки стека, когда функция возвращается и локальные переменные удаляются.
Так как ваша функция теперь возвращает адрес объекта, который был выделен в куче с new
оператор, тогда все будет работать нормально.
Просто не забудьте delete
объект, когда больше не нужно, чтобы избежать утечки памяти.
Код не будет работать, если вы попытаетесь разыменовать указатель на уничтоженный объект. objPtr
не станет автоматически nullptr
так что будь осторожен!
Изменение на OBj localVar = new object()
тоже не будет работать (и может выдать ошибку компиляции, если OBj
не имеет надлежащего конструктора), но вы можете заставить его работать, используя objPtr = new object()
если присваивать object*
куда OBj*
ожидается, является приемлемым (это может быть заархивировано через typedef
наследство и т. д.). Будьте осторожны, чтобы не вызвать утечку памяти!
Правильно ли я считаю, что это никогда не сработает? Поскольку localVar является локальным, он будет уничтожен один раз за пределами функции create, в результате чего objPtr будет иметь адрес пустой памяти, что означает, что objPtr является нулевым указателем?
Да. Кроме указателя не будет null
, Это будет иметь любую ценность. Просто адрес, на который он указывает, больше не содержит объект.
во-вторых, будет ли это работать, если я сделаю это: Obj localVar = new object() или objPtr = new object()
да