原始指针可以指向在堆栈或堆上分配的对象。
堆分配示例:
// 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
。
通常可以避免使用new
和delete
,并避免使用原始指针。对于make_unique
和make_shared
,new
不是必需的。
"智能指针"是否旨在指向堆上动态创建的对象?
它们用于堆分配的对象以防止泄漏。
C++的准则是使用纯指针来引用单个对象(但不拥有它)。对象的所有者按值、容器或通过智能指针保存它。
"智能指针"是否旨在指向堆上动态创建的对象?
是的,但这只是默认设置。请注意,std::unique_ptr
有一个构造函数(否。(3)/(4)在该页面上),它采用您以某种方式获得的指针和您提供的"删除器"。在这种情况下,唯一指针不会对堆执行任何操作(除非您的删除程序这样做)。
对于 C++11,我们是否应该继续使用原始指针来指向堆栈分配的对象?谢谢。
您应该在不"拥有"指针的代码中使用原始指针 - 不需要关注分配或解除分配;无论您是否指向堆、堆栈或其他地方。
另一个使用它的地方是当你为受保护/私有成员实现一些具有复杂所有权模式的类时。
PS:请忘记std::auto_ptr
...假装它从未存在过:-)