在不传递所有权的情况下重新分配函数中的智能指针?
Reassign a smart pointer in a function without passing ownership?
背景
使用普通指针,我可以做类似下面的事情
void conditional_reassign(MyClass* ptr)
{
if (my_condition)
{
delete ptr;
ptr = new MyClass(new_param);
}
}
而且我可以像下面这样传入我想改变的指针
MyClass* ptr = new MyClass(old_param);
conditional_reassign(ptr);
我希望用 std::unique_ptr
重新实现它。这是我想出的
std::unique_ptr<MyClass> conditional_reassign2(std::unique_ptr<MyClass> ptr)
{
if (my_condition)
{
ptr = std::make_unique<MyClass>(new_param);
}
return std::move(ptr);
}
我会这样称呼它
std::unique_ptr<MyClass> ptr = make_unique<MyClass>(old_param);
ptr = std::move(conditional_reassign2(std::move(ptr)));
问题
我对这行的冗长不太满意
ptr = conditional_reassign2(std::move(ptr));
有没有办法实现 conditional_reassign2
以便我可以用类似于 conditional_reassign(ptr)
的方式调用它
编辑
我应该注意
的一个主要问题
ptr = std::move(conditional_reassign2(std::move(ptr)));
是不管my_condition
会破坏ptr
指向的原始对象(见)
您可以定义 conditional_reassign2()
函数来获取 std::unique_ptr
by reference 而不是 by value:
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);
或return指针,需要一次移动
std::unique_ptr<MyClass> conditional_reassign2(std::unique_ptr<MyClass> ptr) {...}
std::unique_ptr<MyClass> myPtr;
myPtr = conditional_reassign2(std::move(myPtr));
您也可以直接从函数 return ptr 而无需显式调用 move。
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
,调用者有一个指向已删除对象的指针,而新创建的对象所在的地址在函数returns之后丢失了。
这是您修复的第一个示例(参数现在是对指针的引用):
void conditional_reassign((MyClass*)& ptr)
{
if (my_condition)
{
delete ptr;
ptr = new MyClass(new_param);
}
}
要使用 unique_ptr,您也可以使用引用而不是 return 任何东西。这样就不需要处理 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);
或者您可以使用 return/move 语义:
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));
背景
使用普通指针,我可以做类似下面的事情
void conditional_reassign(MyClass* ptr)
{
if (my_condition)
{
delete ptr;
ptr = new MyClass(new_param);
}
}
而且我可以像下面这样传入我想改变的指针
MyClass* ptr = new MyClass(old_param);
conditional_reassign(ptr);
我希望用 std::unique_ptr
重新实现它。这是我想出的
std::unique_ptr<MyClass> conditional_reassign2(std::unique_ptr<MyClass> ptr)
{
if (my_condition)
{
ptr = std::make_unique<MyClass>(new_param);
}
return std::move(ptr);
}
我会这样称呼它
std::unique_ptr<MyClass> ptr = make_unique<MyClass>(old_param);
ptr = std::move(conditional_reassign2(std::move(ptr)));
问题
我对这行的冗长不太满意
ptr = conditional_reassign2(std::move(ptr));
有没有办法实现 conditional_reassign2
以便我可以用类似于 conditional_reassign(ptr)
编辑
我应该注意
的一个主要问题ptr = std::move(conditional_reassign2(std::move(ptr)));
是不管my_condition
会破坏ptr
指向的原始对象(见
您可以定义 conditional_reassign2()
函数来获取 std::unique_ptr
by reference 而不是 by value:
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);
或return指针,需要一次移动
std::unique_ptr<MyClass> conditional_reassign2(std::unique_ptr<MyClass> ptr) {...}
std::unique_ptr<MyClass> myPtr;
myPtr = conditional_reassign2(std::move(myPtr));
您也可以直接从函数 return ptr 而无需显式调用 move。
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
,调用者有一个指向已删除对象的指针,而新创建的对象所在的地址在函数returns之后丢失了。
这是您修复的第一个示例(参数现在是对指针的引用):
void conditional_reassign((MyClass*)& ptr)
{
if (my_condition)
{
delete ptr;
ptr = new MyClass(new_param);
}
}
要使用 unique_ptr,您也可以使用引用而不是 return 任何东西。这样就不需要处理 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);
或者您可以使用 return/move 语义:
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));