正确地宣布智能指针

时间:2013-08-31 00:42:37

标签: c++

我有点困惑:

int *pointer = new int[100];    // Yes
int array [] = new int[100];    // No

可是:

unique_ptr<int*> pointer { new int[100] };    // No
unique_ptr<int[]> array { new int[100] };     // Yes

有人可以解释这里涉及的一般原则。我不完全理解为什么智能指针语义似乎与常规原始指针相反。

2 个答案:

答案 0 :(得分:5)

智能指针是库代码,所以它们按照他们的方式工作,因为有人以这种方式设计它们。

在你的第一个裸阵列新代码中,第二行在语法上没有意义,因为你不能用指针初始化数组,new返回一个指针。

unique_ptr示例也是错误的;修正后的版本更有意义:

//               +--------------+------------ pointer to int
//               V              V
std::unique_ptr<int>   p { new int; }
std::unique_ptr<int[]> p { new int[10]; }
//               ^                ^
//               +----------------+---------- pointer to first element
//                                            of an array of int

发现模式?

您需要不同模板特化的原因是您需要在指针上调用deletedelete[],具体取决于它的分配方式,但您无法通过查看原始指针。 (此外,阵列版本提供了一个方便的[] - 运算符。)

停止你混合unique_ptr<int>new int[10]没有什么,但它是一个或多或少的微妙错误导致静默未定义的行为(另一个原因是永远不会使用{{ 1}}你自己而是依靠new!)。相比之下,你的第一个例子是一个简单的语法错误。

答案 1 :(得分:2)

我同意100%的Kerrek SB答案。在这里,我想增加另一个强大的可能性。您还可以定义自定义删除类

 auto deleter= [](int* ptr){delete[] ptr;};
 std::unique_ptr<int, decltype(deleter)> ptr4(new int[100], deleter);

这看起来很复杂,但是如果你需要调用一些需要C语言结构的堆分配的C库,它会非常有用

具体示例:GSL GNU科学库。集成例程需要分配名为“gsl_integration_workspace”的结构。在这种情况下,您可以使用以下代码来确保您的代码是异常安全的

 auto deleter= [](gsl_integration_workspace* ptr) {
   gsl_integration_workspace_free(ptr);
 };
 std::unique_ptr<gsl_integration_workspace, decltype(deleter)> ptr4 (
 gsl_integration_workspace_alloc (2000), deleter);

正如Kerrek SB所说,因为智能指针是库代码,所以它们提供了比原始指针更强大的内存管理方式。