简体   繁体   English

在不传递所有权的情况下在函数中重新分配智能指针?

[英]Reassign a smart pointer in a function without passing ownership?

Background 背景

With normal pointers, I can do something like the following 使用普通的指针,我可以执行以下操作

void conditional_reassign(MyClass* ptr)
{
    if (my_condition)
    {
        delete ptr;
        ptr = new MyClass(new_param);
    }
}

And I can pass in the pointer I want to change like following 我可以像下面那样传递我想要更改的指针

MyClass* ptr = new MyClass(old_param);
conditional_reassign(ptr);

I wish to reimplement this with std::unique_ptr . 我想用std::unique_ptr重新实现。 Here's what I came up with 这是我想出的

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);
}

And I would call it with the following 我会用以下内容来称呼它

std::unique_ptr<MyClass> ptr = make_unique<MyClass>(old_param);
ptr = std::move(conditional_reassign2(std::move(ptr)));

Question

I'm not quite happy with the verbosity of the line 我对这行的详细程度不太满意

ptr = conditional_reassign2(std::move(ptr));

Is there a way to implement conditional_reassign2 so that I can call it in a manner similar to conditional_reassign(ptr) 有没有一种方法可以实现conditional_reassign2所以我可以用类似于conditional_reassign(ptr)的方式来调用它

Edit 编辑

I should note a major issue with 我应该注意一个主要问题

ptr = std::move(conditional_reassign2(std::move(ptr)));

is that it will destroy the original object ptr pointed to regardless of my_condition (see Why does reassigning a smart pointer to itself cause destruction? ) 不管my_condition是否都会破坏指向的原始对象ptr (请参阅为什么将智能指针重新分配给自身会导致破坏?

Either you need to pass the pointer by reference 您要么需要通过引用传递指针

void conditional_reassign2(std::unique_ptr<MyClass>& ptr) {...}

std::unique_ptr<MyClass> myPtr;
conditional_reassign2(myPtr);

or return the pointer, which requires a single move 或返回指针,只需移动一下

std::unique_ptr<MyClass> conditional_reassign2(std::unique_ptr<MyClass> ptr) {...}

std::unique_ptr<MyClass> myPtr;
myPtr = conditional_reassign2(std::move(myPtr));

Also you can return ptr directly from the function without explicitly calling move. 另外,您可以直接从函数返回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;
}

You can define the conditional_reassign2() function to take the std::unique_ptr by reference instead of by value : 您可以定义conditional_reassign2()函数以通过引用而不是通过值获取std::unique_ptr

void conditional_reassign2(std::unique_ptr<MyClass>& ptr)
{
    if (my_condition)
    {
        ptr = std::make_unique<MyClass>(new_param);
    }
}

This way the function can directly modify the instance that is being passed, no need to transfer the ownership. 这样,函数可以直接修改正在传递的实例,而无需转移所有权。

Assuming that ptr is an std::unique_ptr<MyClass> , then calling conditional_reassign2() would be in this case: 假设ptrstd::unique_ptr<MyClass> ,则在这种情况下调用conditional_reassign2()将是:

conditional_reassign2(ptr);

Your first example does not do what you intend it to do. 您的第一个示例未达到您的预期目的。 As ptr is passed by value, the caller's pointer will not be modified. 当通过值传递ptr ,将不会修改调用方的指针。 So if my_condition is true , the caller has a pointer that points to a deleted object, and the address to which the newly created object is stored at is lost after the function returns. 因此,如果my_conditiontrue ,则调用方将拥有一个指向已删除对象的指针,并且该函数返回后,新创建的对象所存储的地址将丢失。

Here is your first example fixed (the argument is now a reference to a pointer): 这是您的第一个固定示例(参数现在是对指针的引用):

void conditional_reassign((MyClass*)& ptr)
{
    if (my_condition)
    {
        delete ptr;
        ptr = new MyClass(new_param);
    }
}

To use unique_ptr, you can also use references and not return anything. 要使用unique_ptr,您还可以使用引用而不返回任何内容。 This way no need to deal with std::move 这样就无需处理std::move

void conditional_reassign2(std::unique_ptr<MyClass>& ptr)
{
    if (my_condition)
    {
        ptr =  std::make_unique<MyClass>(new_param);
    }
}

You can call it like this: 您可以这样称呼它:

std::unique_ptr<MyClass> ptr = make_unique<MyClass>(old_param);
conditional_reassign2(ptr);

Or you can use return/move semantics: 或者,您可以使用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;
}

And call it like this: 并这样称呼它:

std::unique_ptr<MyClass> ptr = make_unique<MyClass>(old_param);
ptr = conditional_reassign2(std::move(ptr));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM