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

"智能指针"是否旨在用于指向堆上动态创建的对象? 对于 C++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.

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

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

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

至于应该做什么,嗯,它有助于考虑存储持续时间,特别是对象是如何创建的。

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

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

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

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

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

"智能指针"是否旨在指向堆上动态创建的对象?

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

C++的准则是使用纯指针来引用单个对象(但不拥有它)。对象的所有者按值、容器或通过智能指针保存它。

"智能指针"是否旨在指向堆上动态创建的对象?

是的,但这只是默认设置。请注意,std::unique_ptr有一个构造函数(否。(3)/(4)在该页面上),它采用您以某种方式获得的指针和提供的"删除器"。在这种情况下,唯一指针不会对堆执行任何操作(除非您的删除程序这样做)。

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

您应该在不"拥有"指针的代码中使用原始指针 - 不需要关注分配或解除分配;无论您是否指向堆、堆栈或其他地方。

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

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

相关内容

  • 没有找到相关文章

最新更新