将原始指针传递给接受unique_ptr作为参数的函数

Pass raw pointer to function that accepts unique_ptr as parameter

本文关键字:ptr 参数 函数 unique 指针 原始      更新时间:2023-10-16

我正在尝试编写一个函数,该函数接受对派生自Base类的unique_ptr作为参数(以指示所有权转移(。我想出了以下代码:

#include <memory>
#include <type_traits>
class Base
{
public:
Base() {}
};
class Derived : public Base
{
public:
Derived() {}
};

void foo(std::unique_ptr<Derived> _data) {}
template <class T>
void boo(std::unique_ptr<T> _data) {
static_assert(std::is_convertible<T*, Base*>::value,
"Only classes derived from Base can be used as "
"parameter for boo");
}

int main() { foo(new Derived); }

但是当我尝试编译它时,我收到一个错误,告诉我如果我使用foocould not convert ‘(operator new(1ul), (<statement>, ((Derived*)<anonymous>)))’ from ‘Derived*’ to ‘std::unique_ptr<Derived>’,当我使用boo时相同(加上一些模板详细信息(。如果我正确理解了所有内容,我被告知的是没有std::unique_ptr<Derived>的构造函数可以接受Derived指针。但是当我在cppreference页面上查找unqiue_ptr构造函数时,我看到有这样的构造函数(数字3-4(。

问题是:如何创建一个接受unique_ptr作为参数并使用原始指针调用它的函数。

附言我正在尝试编写一个接受unique_ptr的函数,因为我想指示参数的所有权将被转移。如果你知道如何编写一个带有签名的函数,可以清晰明确地表明所有权正在转移,我也会接受这个答案。此函数可以使用static_assertBase指针作为参数进行模板。

附言主要问题是如何制作foo(new Derived).我知道我可以使用boo(std::make_unique<Derived>())(在这种情况下一切正常(,但我也真的很想知道为什么带有原始指针的示例不起作用,因为我不知道如何指示我正在"窃取"原始指针的所有权。

附言用法示例(使用原始指针((不起作用(

Derived* derived_1 = new Derived;
// Do something with derived_1
boo(derived_1); // Pass to function and don't worry about `delete`
// because you know that ownership has been
// transferred and no longer is your concern

并带有智能指针

void foo_2(std::unique_ptr<Derived>& _data) {
boo(std::move(_data)); 
}
std::unique_ptr<Derived> derived_2 = std::make_unique<Derived>();
// Do something with derived_2
foo(std::move(derived_2)); // Have to use `std::move`
// or
foo_2(derived_2);

第二个(省略对新功能的需求(并不像第一个那么简单(尽管我应该承认差异不是那么大(也许是 2 倍打字((

重载 3 和 4 在这里不适用。 他们的签名是

unique_ptr( pointer p, /* see below */ d1 ) noexcept;
unique_ptr( pointer p, /* see below */ d2 ) noexcept;

他们采用第二个参数,即自定义删除器。 唯一适用的重载是 2,即

explicit unique_ptr( pointer p ) noexcept;

由于它被标记为显式,因此不会将指针隐式转换为unique_ptr。 这是一个安全问题,明确说明是正确的。 如果不是explicit那么

void foo(std::unique_ptr<int> _data) {}
int main()
{
int bar;
foo(&bar);
}

将编译,但这将是未定义的行为,因为_data会在foo结束时销毁指针时尝试删除指针。

您必须在转换中明确

int main()
{
Derived* d = nullptr;
BadInterface(&d); // mainly d = new Derived(..);
foo(std::unique_ptr<Derived>(d));
}

在您的一个衬里案例中给出:

foo(std::unique_ptr<Derived>(new Derived));