使用本地原始指针初始化std :: unique_ptr会发生什么?

时间:2018-06-21 03:55:55

标签: c++ unique-ptr

一段代码片段:

std::unique_ptr<SDL_Renderer, decltype(&SDL_DestroyRenderer)>
cGraphics::Create_Renderer()
{
    SDL_Renderer* temprenderer = SDL_CreateRenderer(m_Window.get(), -1, 0);
    SDL_SetRenderDrawColor(temprenderer, 255, 255, 255, 0xff);
    return std::unique_ptr<SDL_Renderer,
                           decltype(&SDL_DestroyRenderer)>(temprenderer,
                                                           SDL_DestroyRenderer);
}

我所知道的:

  • temprenderer当然超出范围时会被销毁;
  • 使用原始指针初始化临时std::unique_ptr
  • 尽管std::unique_ptr不允许复制,但可以按值返回;
  • 基本上,临时std::unique_ptr超出范围时也会被销毁;
  • 我们现在持有该临时唯一指针的副本

我的问题:

为什么原始指针的破坏对临时唯一指针的副本没有影响,而临时唯一指针的副本本身(临时唯一指针)是用原始指针初始化的?换句话说,在防止信息丢失的唯一指针内部发生了什么?

我的假设是,唯一指针也包含一个原始指针(例如.get()),当它由temprenderer启动时,它将temprenderer的值复制到原始指针中,当唯一指针超出范围时,该信息将再次被复制。

好的,经过深思熟虑,这听起来很明显,但是如果有人可以确认这一点,我将不胜感激。我也发现了这一点:

  

unique_ptr明确禁止复制其包含的指针(正常分配时会发生这种情况)

所以当我们返回unique_ptr时也许还会发生一些额外的事情吗?

2 个答案:

答案 0 :(得分:1)

当我们返回临时unique_ptr时,编译器实际上通过调用move构造函数来“移动”资源。一旦移动了资源,原始临时unique_ptr就超出范围并被销毁。即使unique_ptr是左值,但即使编译器发现函数返回后它仍然会超出范围(不再需要),它也会执行 copy Elision 并选择返回的move构造函数。

  

为什么原始指针的破坏对临时唯一指针的副本没有影响,而临时唯一指针的副本本身(临时唯一指针)是用原始指针初始化的?换句话说,在防止信息丢失的唯一指针内部发生了什么?

因为不是要破坏的内容,而是保存地址的变量。并且unique_ptr一旦拥有内容的地址,为什么仍然重要呢?

  

我的假设是,唯一指针还包含一个原始指针(例如.get()),当它由temprenderer启动时,它将temprenderer的值复制到原始指针上,并且当唯一指针超出范围。

unique_ptr初始化temprenderer时,它只是将temprenderer指向的地址复制到其自己的成员变量中。当控件超出范围时,该信息将不复制,而是移动(所有权转移)

您可能想看看unique_ptr is returned from a function

答案 1 :(得分:1)

  

unique_ptr明确禁止复制其包含的指针(如   通常会发生这种情况)

template<class U, class E>
unique_ptr(unique_ptr<U, E>&& u) noexcept;

U是MoveConstructible和MoveAssignable的,但是按照unique.ptr/4 不是 CopyConstructible CopyAssignable 的。

因此,它可以防止复制。相反,它会转让所有权。