C++ 在函数中重新分配智能指针而不传递所有权? 出身背景

C++ 在函数中重新分配智能指针而不传递所有权? 出身背景,c++,smart-pointers,C++,Smart Pointers,使用普通指针,我可以执行如下操作 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<MyClass>

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

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<MyClass> ptr = make_unique<MyClass>(old_param);
ptr = std::move(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<MyClass> ptr = make_unique<MyClass>(old_param);
ptr = std::move(conditional_reassign2(std::move(ptr)));
我希望用std::unique\u 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);
}
有没有一种方法可以实现条件_-reassign2,这样我就可以用类似于条件_-reassignptr的方式调用它

编辑 我应该注意到一个重大问题

ptr = std::move(conditional_reassign2(std::move(ptr)));
无论my_条件如何,它都会破坏指向的原始对象ptr请参见

您可以定义条件_reassign2函数,通过引用而不是通过值获取std::unique_ptr:

您可以定义条件_reassign2函数,以通过引用而不是通过值获取std::unique_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,而无需显式调用move

std::unique_ptr<MyClass> conditional_reassign2(std::unique_ptr<MyClass> ptr)
{
    if (my_condition)
        ptr = std::make_unique<MyClass>(new_param);
    return 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,而无需显式调用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_条件为true,则调用方有一个指向已删除对象的指针,并且在函数返回后,新创建的对象的存储地址将丢失

这是您的第一个示例修复了参数现在是指针的引用:

void conditional_reassign((MyClass*)& ptr)
{
    if (my_condition)
    {
        delete ptr;
        ptr = new MyClass(new_param);
    }
}
要使用unique_ptr,还可以使用引用而不返回任何内容。这样就不需要处理std::move

你可以这样称呼它:

std::unique_ptr<MyClass> ptr = make_unique<MyClass>(old_param);
conditional_reassign2(ptr);
std::unique_ptr<MyClass> ptr = make_unique<MyClass>(old_param);
ptr = conditional_reassign2(std::move(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);
conditional_reassign2(ptr);
std::unique_ptr<MyClass> ptr = make_unique<MyClass>(old_param);
ptr = conditional_reassign2(std::move(ptr));

你的第一个例子并没有达到你的目的。由于ptr是按值传递的,因此不会修改调用方的指针。因此,如果my_条件为true,则调用方有一个指向已删除对象的指针,并且在函数返回后,新创建的对象的存储地址将丢失

这是您的第一个示例修复了参数现在是指针的引用:

void conditional_reassign((MyClass*)& ptr)
{
    if (my_condition)
    {
        delete ptr;
        ptr = new MyClass(new_param);
    }
}
要使用unique_ptr,还可以使用引用而不返回任何内容。这样就不需要处理std::move

你可以这样称呼它:

std::unique_ptr<MyClass> ptr = make_unique<MyClass>(old_param);
conditional_reassign2(ptr);
std::unique_ptr<MyClass> ptr = make_unique<MyClass>(old_param);
ptr = conditional_reassign2(std::move(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);
conditional_reassign2(ptr);
std::unique_ptr<MyClass> ptr = make_unique<MyClass>(old_param);
ptr = conditional_reassign2(std::move(ptr));

如果我误读了你的问题,我向你道歉,但有条件的重新分配并不像你想象的那样。它不会改变呼叫者的ptr。为此,您需要通过引用传递它,或使函数采用指向指针的指针。外部std::move是多余的。为什么要将相同的ptr用作返回值和参数?您指出的条件_重新分配函数会导致未定义的行为,这是为什么应该将代码转换为使用unique_ptr的一个主要示例。使用unique_ptr更难实现您当前的错误:-如果我误读了您的问题,请道歉,但条件_重新分配并没有达到您似乎认为的效果。它不会改变呼叫者的ptr。为此,您需要通过引用传递它,或使函数采用指向指针的指针。外部std::move是多余的。为什么要将相同的ptr用作返回值和参数?您指出的条件_重新分配函数会导致未定义的行为,这是为什么应该将代码转换为使用unique_ptr的一个主要示例。使用unique_ptr更难实现您当前的错误:-