为啥 unique_ptr<T> 不能从 T* 构造?

Posted

技术标签:

【中文标题】为啥 unique_ptr<T> 不能从 T* 构造?【英文标题】:Why is unique_ptr<T> not constructible from T*?为什么 unique_ptr<T> 不能从 T* 构造? 【发布时间】:2021-02-25 16:28:05 【问题描述】:

这个代码有什么“错误”,举个简单的例子?

unique_ptr<char> meow = strdup("meow");

无论我是否为unique_ptr 模板提供“删除器”参数,都无法从T* 分配unique_ptr&lt;T&gt;

&lt;memory&gt; 为什么不提供这个看似直观的快捷方式?这仅仅是一种疏忽,还是出于某种原因,这种可分配性从根本上来说是个坏主意?

【问题讨论】:

应该是:std::unique_ptr&lt;char[]&gt; meowstrdup("meow"); 这能回答你的问题吗? unique_ptr operator= “为什么 不提供这个看似直观的快捷方式?” - 正是如此。它简单直观,无需了解所有权影响即可轻松(ab)使用。谁不喜欢摸索一个 MLOC 代码库来发现= 的潜在错误用法?甚至auto_ptr 也从未提供过。 请注意,即使meow = strdup() 可以工作,您也必须使用调用free() 的自定义删除器,而不是调用delete 【参考方案1】:

&lt;memory&gt; 为什么不提供这个看似直观的快捷方式?

想象一下你有

int bar;

    int * foo = &bar;
    std::unique_ptr<int> uptr = foo;
    // use uptr

uptr 超出范围时,它会尝试执行delete pointer;,这将尝试在new 未分配的内存上调用delete。这是未定义的行为,可能会导致各种问题。标准不允许编写这样的错误代码,而不是允许它。

如果您确实确定要从现有指针构造unique_ptr,并且您知道默认删除器就是您想要的,那么您可以使用以下形式

auto pointer_name = std::unique_ptr<type>(pointer_i_know_needs_to_be_deleted);

【讨论】:

@NicolBolas IIRC,std::unique_ptr 不会关闭 CTAD,因为您无法区分 unique_ptr(new int);unique_ptr(new int[10]); 我可以想象 很多 其他程序员错误 - 包括显式释放之前给 unique_ptr 的指针。您提出的构造有效,但是,该死的,它不能转换为T*——甚至不能转换为const T* @MikhailT。 - 是的,它可以。你打电话给get(),你会得到一个T* @MikhailT。 它不能转换成T*——甚至不能转换成const T* 是什么意思?您是在谈论将unique_ptr 传递给采用原始指针的函数吗?如果是这样,那么您需要使用 get 从中获取原始指针。指针很难正确。与原始指针不同,unique_ptr 旨在尝试限制您可以使用它做的错误。 @MikhailT。随着时间的推移,隐式转换被认为比让程序员输入更多的字母更危险(修复错误的时间)。转换运算符可能会参与意外转换,从而导致难以诊断错误。要跟进,您可以研究为什么(例如)std::string 具有 c_str() 而不是隐式转换运算符。

以上是关于为啥 unique_ptr<T> 不能从 T* 构造?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能将 new 创建的 &client 对象分配给 unique_ptr

第20课 unique_ptr独占型智能指针

unique_ptr<T> 和 unique_ptr<T>&& 之间的区别 [重复]

为啥我不能在 C++14 的 lambda 中移动 std::unique_ptr?

将所有权从 unique_ptr<T,void(*)(T*)> 转移到 unique_ptr<const T,void(*)(const T*)>

`unique_ptr< T const [] >` 是不是应该接受 `T*` 构造函数参数?