unique_ptr堆和堆栈分配

Car*_*ran 10 pointers smart-pointers heap-memory unique-ptr c++11

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

堆分配示例:

// heap allocation
int* rawPtr = new int(100);
std::cout << *rawPtr << std::endl;      // 100
Run Code Online (Sandbox Code Playgroud)

堆栈分配示例:

int i = 100;
int* rawPtr = &i;
std::cout << *rawPtr << std::endl;      // 100
Run Code Online (Sandbox Code Playgroud)

使用auto_ptr示例堆分配:

int* rawPtr = new int(100);
std::unique_ptr<int> uPtr(rawPtr);
std::cout << *uPtr << std::endl;        // 100
Run Code Online (Sandbox Code Playgroud)

使用auto_ptr示例堆栈分配:

int i = 100;
int* rawPtr = &i;
std::unique_ptr<int> uPtr(rawPtr);      // runtime error
Run Code Online (Sandbox Code Playgroud)

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

Tre*_*ntP 11

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

您的代码在上一个示例中崩溃的原因是因为"已删除delete"部分.当它超出范围时,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.
Run Code Online (Sandbox Code Playgroud)


wal*_*lly 5

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

如果已经创建了具有动态存储持续时间的对象(通常实现为在“堆”上创建),则“智能指针”将无法正确运行,如运行时错误所示。

是否打算使用“智能指针”来指向堆上动态创建的对象?对于C ++ 11,我们是否应该继续使用原始指针指向堆栈分配的对象?

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

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

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

auto uPtr = std::make_unique<int>(100);
Run Code Online (Sandbox Code Playgroud)

uPtr会自动存储时间和当它的范围之会调用析构函数。在int将具有动态存储持续时间(堆)和将被delete由智能指针编

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