你为什么要在c ++中创建一个指向原始类型的唯一指针?

时间:2018-01-10 18:11:38

标签: c++ unique-ptr

我刚刚发现了这段代码,谁知道它来自何处或何时,但它是函数的结尾,而不是返回一个简单的int64_t类型,它为它创建了一个unique_ptr。

我只是想知道是否有人可以解释这种用法有何价值?

return std::make_unique<int64_t>(off);

更新

它不是以这种方式使用的,但正如我在下面评论的那样,一个可能使用指向原语的指针而只是原语是你可以将指针设置为null,从而为整数添加一个标志错误或不可用。

2 个答案:

答案 0 :(得分:1)

将原始类型的变量声明为

int64_t foo;

意味着foo被放置在堆栈上并且是block-scoped(即,它在块的末尾超出范围)。更正式地使用C ++术语它有automatic storage duration

  

对象在封闭代码块的开头分配,并在最后解除分配。除了声明为static,extern或thread_local的那些外,所有本地对象都有此存储持续时间。

另一方面,使用unique_ptr ...

auto foo = std::make_unique<int64_t>(off);

...为堆上的int64_t分配内存。形式上,它有dynamic storage duration

  

使用动态内存分配函数为每个请求分配和取消分配对象。

您可以通过声明指向int64_t并使用new的指针来自行完成此操作:

int64_t *foo = new int64_t;

但是你必须确保你不要忘记delete那个指针。这就是unique_ptr的用武之地。当它超出范围时,它会删除它拥有的指针。这是RAII。您还可以将所有权转移到其他unique_ptr实例。

答案 1 :(得分:1)

通过将unique_ptr移动到其他位置,可以扩展unique_ptr指向整数的生命周期。

自动存储整数的生命周期在范围或封闭对象时终止。

如果不仅整数的值,而是整数的身份,那么unique_ptr可以解决原始整数不能解决的问题。

例如,我可以将unique_ptr与线程配对。该线程可以负责将信息写入所述unique_ptr

线是可移动的;原始整数不是。所以两者的语义不一致,所以你不能将一个线程和一个原始int推入一个结构或类中,并使用默认的移动操作。

如果你使用一个线程和一个唯一的ptr到一个基本类型,你可以把它扔进一个结构并使用默认的移动操作,它们可以工作。

您可以使用共享ptr,但是如果我们假设两个对象(唯一的ptr和线程)绑定在首先销毁线程的结构中,则不需要其他共享,并且共享ptr具有开销成本。此外,共享ptr如果暴露导致所有权跟踪地狱。共享ptr的运行时成本是第二次分配和原子递增/递减的混合,导致并发争用成本。编译时的成本是所有权语义比独特的ptr更复杂。

更有可能是一个糟糕的设计决定,但有可能出现原因。