unique_ptr堆和堆栈分配

时间:2017-03-20 17:56:52

标签: c++11 pointers smart-pointers heap-memory unique-ptr

原始指针可以指向在堆栈上或堆上分配的对象。

堆分配示例:

// heap allocation
int* rawPtr = new int(100);
std::cout << *rawPtr << std::endl;      // 100

堆栈分配示例:

int i = 100;
int* rawPtr = &i;
std::cout << *rawPtr << std::endl;      // 100

使用auto_ptr进行堆分配示例:

int* rawPtr = new int(100);
std::unique_ptr<int> uPtr(rawPtr);
std::cout << *uPtr << std::endl;        // 100

使用auto_ptr示例堆栈分配:

int i = 100;
int* rawPtr = &i;
std::unique_ptr<int> uPtr(rawPtr);      // runtime error

智能指针&#39;是否用于指向堆上动态创建的对象?对于C ++ 11,我们是否应该继续使用原始指针来指向堆栈分配的对象?谢谢。

4 个答案:

答案 0 :(得分:5)

智能指针通常用于指向使用new分配的对象,并使用delete删除。它们不必以这种方式使用,但如果我们想要猜测语言结构的预期用途,那似乎就是意图。

您的代码在上一个示例中崩溃的原因是因为&#34;已删除了delete&#34;部分。当它超出范围时,unique_ptr将尝试delete它有指针的对象。由于它是在堆栈上分配的,因此失败了。就像你写过delete rawPtr;

一样

由于通常使用带有堆对象的智能指针,因此有一个函数可以在堆上进行分配并一次性转换为智能指针。 std::unique_ptr<int> uPtr = make_unique<int>(100);将执行第三个示例的前两行的操作。共享指针也有匹配的make_shared

可以使用带有堆栈对象的智能指针。你要做的是指定智能指针使用的删除器,提供一个不调用delete的删除器。由于它是一个堆栈变量并且不需要删除它,所以删除器无能为力。这让人问,那么智能指针的重点是什么,如果它只是调用一个什么都不做的函数?这就是为什么你不常常看到与堆栈对象一起使用的智能指针。但这是一个显示一些有用性的例子。

{
    char buf[32];
    auto erase_buf = [](char *p) { memset(p, 0, sizeof(buf)); };
    std::unique_ptr<char, decltype(erase_buf)> passwd(buf, erase_buf);

    get_password(passwd.get());
    check_password(passwd.get());
}
// The deleter will get called since passwd has gone out of scope.
// This will erase the memory in buf so that the password doesn't live
// on the stack any longer than it needs to.  This also works for
// exceptions!  Placing memset() at the end wouldn't catch that.

答案 1 :(得分:3)

运行时错误是由于delete在从未使用new分配的内存位置上调用的事实。

如果已经使用dynamic storage duration创建了一个对象(通常在&#39;堆上实现创建),那么“智能指针”将被创建。如运行时错误所示,它将无法正常运行。

  

智能指针&#39;旨在用于动态指向   在堆上创建了对象?对于C ++ 11,我们应该继续   使用原始指针指向堆栈分配的对象?

至于应该做什么,这有助于考虑存储持续时间,特别是对象的创建方式。

  • 如果对象具有自动存储持续时间(堆栈),则避免获取地址并使用引用。所有权不属于指针,引用使所有权更清晰。
  • 如果对象具有动态存储持续时间(堆),则可以使用智能指针,因为它可以管理所有权。

所以对于最后一个例子,以下会更好(指针拥有int):

auto uPtr = std::make_unique<int>(100);

uPtr将具有自动存储持续时间,并在超出范围时调用析构函数。 int将具有动态存储持续时间(堆),并由智能指针进行delete

通常可以避免使用newdelete并避免使用原始指针。使用make_uniquemake_sharednew并非必需。

答案 2 :(得分:3)

  

智能指针&#39;是否用于指向堆上动态创建的对象?

它们用于堆分配的对象以防止泄漏。

C ++的指导原则是使用引用的普通指针指向单个对象(但不拥有它)。对象的所有者通过值,容器或智能指针保存它。

答案 3 :(得分:1)

  

智能指针&#39;是否用于指向堆上动态创建的对象?

是的,但那只是默认值。请注意std::unique_ptr在该页面上有一个constructor(no(3)/(4)),它带有以某种方式获得的指针,以及一个&#34;删除器&#34; 提供的。在这种情况下,唯一指针不会对堆做任何事情(除非你的删除器这样做)。

  

对于C ++ 11,我们是否应该继续使用原始指针来指向堆栈分配的对象?谢谢。

你应该在没有&#34;拥有&#34;的代码中使用原始指针。指针 - 不需要关心分配或释放;无论你是指向堆还是堆栈或其他地方,都是如此。

另一个使用它的地方是当你为受保护/私人成员实施一些具有复杂所有权模式的类时。

PS:请忘记std::auto_ptr ...假装它从未存在过: - )