Как будто вы пытаетесь получить доступ к объекту, который является null
. Рассмотрим ниже пример:
TypeA objA;
. В это время вы только что объявили этот объект, но не инициализировали или не инициализировали. И всякий раз, когда вы пытаетесь получить доступ к каким-либо свойствам или методам в нем, он будет генерировать NullPointerException
, что имеет смысл.
См. Также этот пример:
String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
Вы можете определить функцию conditional_reassign2()
для получения std::unique_ptr
по ссылке вместо по значению :
void conditional_reassign2(std::unique_ptr<MyClass>& ptr)
{
if (my_condition)
{
ptr = std::make_unique<MyClass>(new_param);
}
}
Таким образом, функция может напрямую измените передаваемый экземпляр, нет необходимости передавать права собственности.
Предполагая, что ptr
является std::unique_ptr<MyClass>
, тогда вызов conditional_reassign2()
будет в этом случае:
conditional_reassign2(ptr);
Либо вам нужно передать указатель по ссылке
void conditional_reassign2(std::unique_ptr<MyClass>& ptr) {...}
std::unique_ptr<MyClass> myPtr;
conditional_reassign2(myPtr);
или вернуть указатель, для которого требуется один ход
std::unique_ptr<MyClass> conditional_reassign2(std::unique_ptr<MyClass> ptr) {...}
std::unique_ptr<MyClass> myPtr;
myPtr = conditional_reassign2(std::move(myPtr));
Также вы можете вернуть ptr непосредственно из функции без явно вызывающий ход.
std::unique_ptr<MyClass> conditional_reassign2(std::unique_ptr<MyClass> ptr)
{
if (my_condition)
ptr = std::make_unique<MyClass>(new_param);
return ptr;
}
Ваш первый пример не делает то, что вы намерены делать. Поскольку ptr
передается по значению, указатель вызывающего не будет изменен. Поэтому, если my_condition
равно true
, у вызывающей стороны есть указатель, который указывает на удаленный объект, и адрес, по которому сохраняется вновь созданный объект, теряется после возврата из функции.
Вот ваш первый исправленный пример (теперь аргумент является ссылкой на указатель):
void conditional_reassign((MyClass*)& ptr)
{
if (my_condition)
{
delete ptr;
ptr = new MyClass(new_param);
}
}
Чтобы использовать unique_ptr, вы также можете использовать ссылки и ничего не возвращать. Таким образом, нет необходимости иметь дело с std::move
void conditional_reassign2(std::unique_ptr<MyClass>& ptr)
{
if (my_condition)
{
ptr = std::make_unique<MyClass>(new_param);
}
}
Вы можете назвать это так:
std::unique_ptr<MyClass> ptr = make_unique<MyClass>(old_param);
conditional_reassign2(ptr);
Или вы можете использовать семантику возврата / перемещения:
std::unique_ptr<MyClass> conditional_reassign(std::unique_ptr<MyClass> ptr)
{
if (my_condition)
{
return std::make_unique<MyClass>(new_param);
}
return ptr;
}
И назовите это так:
std::unique_ptr<MyClass> ptr = make_unique<MyClass>(old_param);
ptr = conditional_reassign2(std::move(ptr));