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

时间:2019-04-11 09:37:42

标签: c++ smart-pointers

背景

使用普通指针,我可以执行以下操作

<jboss-deployment-structure>
    <deployment>
        <exclusions>
            <module name="com.fasterxml.jackson.core.jackson-core" />
            <module name="com.fasterxml.jackson.core.jackson-annotations" />
            <module name="com.fasterxml.jackson.core.jackson-databind" />
            <module name="com.fasterxml.jackson.datatype.jackson-datatype-jdk8" />
            <module name="com.fasterxml.jackson.datatype.jackson-datatype-jsr310" />
            <module name="com.fasterxml.jackson.jaxrs.jackson-jaxrs-json-provider" />
            <module name="org.jboss.resteasy.resteasy-jackson2-provider" />
            <module name="org.jboss.resteasy.resteasy-jackson-provider" />

            <module name="com.fasterxml.jackson.core.databind"/>
        </exclusions>
    </deployment>
</jboss-deployment-structure>

然后我可以像下面那样传递要更改的指针

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))); ,而与ptr无关(请参见Why does reassigning a smart pointer to itself cause destruction?

3 个答案:

答案 0 :(得分:3)

要么需要通过引用传递指针

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,而无需显式调用move。

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

答案 1 :(得分:1)

您可以定义conditional_reassign2()函数,以使用std::unique_ptr通过引用 而不是通过按值

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

通过这种方法,该函数可以直接修改正在传递的实例,而无需转移所有权。

假设ptrstd::unique_ptr<MyClass>,则在这种情况下调用conditional_reassign2()

conditional_reassign2(ptr);

答案 2 :(得分:0)

您的第一个示例未达到您的预期目的。当ptr按值传递时,调用者的指针将不会被修改。因此,如果my_conditiontrue,则调用者将拥有一个指向已删除对象的指针,并且该函数返回后,新创建的对象所存储的地址将丢失。

这是第一个固定的示例(参数现在是对指针的引用):

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

或者您可以使用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));