Я хочу проверить, правильно ли я понимаю. Если бы у меня было следующее в моем заголовке:
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()
Правильно ли я считаю, что это никогда не сработает?
Только частично. Вам может повезти, и это может сработать, но поведение, как ожидается, будет непредсказуемым (или, более конкретно, не определено) и является определенно ошибка в коде.
Причина в том, что контент может присутствовать или не присутствовать по указанному адресу. Точка, в которой память используется для 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, чтобы иметь адрес пустой памяти, что означает objPtr
такое нулевой указатель?
Да. Кроме указателя не будет null
, Это будет иметь любую ценность. Просто адрес, на который он указывает, больше не содержит объект.
во-вторых, будет ли это работать, если я сделаю это: Obj localVar = new object () или
objPtr = новый объект ()
да
Код не будет работать, если вы попытаетесь разыменовать указатель на уничтоженный объект. objPtr
не станет автоматически nullptr
так что будь осторожен!
Изменение на OBj localVar = new object()
тоже не будет работать (и может выдать ошибку компиляции, если OBj
не имеет надлежащего конструктора), но вы можете заставить его работать, используя objPtr = new object()
если присваивать object*
куда OBj*
ожидается, является приемлемым (это может быть заархивировано через typedef
наследство и т. д.). Будьте осторожны, чтобы не вызвать утечку памяти!