我问这个问题可以减轻我对以下程序的困惑。我知道在某些上下文中使用数组会使数组衰减为指向其第一个元素的单个指针。我有一个函数,通过指针返回此数组(此函数使用new[]
创建)。数组是否会衰减,导致指针只指向第一个元素?这是一个例子:
int *foo() {
int *t = new int[10];
return t;
}
int main() {
int *p = foo();
}
这是混乱的地方。我不知道p
是指向第一个元素还是指向整个数组。所以我有以下问题:
p
是否指向数组的第一个元素?delete[]
上使用p
会导致未定义的行为吗?我希望这些问题能得到解答,这样我才能完全理解这个程序。谢谢。
答案 0 :(得分:7)
通过指针返回数组会导致它的衰减(并因此导致内存泄漏)吗?
您实际上正在返回t
的副本,这是一个指针。它已经指向动态分配的数组的第一个元素。如果您未能在其上调用delete []
,则只会发生内存泄漏。
p是否指向数组的第一个元素?
是
如果上面两个是真的,在p上使用delete []会导致未定义的行为吗?
不,这样做很好。只要该函数返回一个指向动态分配数组的指针。
你已经发现了这个成语的一个严重问题:你不知道你是否得到一个指向元素的指针,一个指向动态分配数组的第一个元素的指针,一个指向全局的指针。您无法通过查看函数的返回类型来了解是否需要调用delete
,delete []
,或者根本不调用delete。解决方案:不要返回指针!返回一个beter表示正在发生的事情的类型,它负责管理自己的资源(std::vector
,std::array
,std::unique_ptr
,std::shared_ptr
...)。< / p>
答案 1 :(得分:6)
你的函数分配内存并向它返回一个指针,或者更专业地,返回第一个元素,正如你所知道的那样。
之后记忆的内容是直到来电者。这意味着当返回的数组不再使用时,调用者应使用 delete[]
删除它。如果调用者不遵守此规则,则程序会泄漏内存。如果你编写这样的代码,你应该在方法的文档中强调这一点!
更现代的解决方案就是使用智能指针。智能指针本身就是保护底层指针的对象(不是指针的指针)。根据我们在这里讨论的智能指针的类型,它将在调用者超出范围时自动删除(唯一保留所分配内存的所有权),或者当其他人不再使用它时(共享所有权)
有关详细信息,请参阅此问题:smart pointers and arrays
现在,如果函数是像你的问题一样编写的,那么它返回一个原始指针而不是一个智能指针,你仍然可以通过在后面包装数组来利用调用者中智能指针的功能。
关于要删除的元素数量/内存量,这完全取决于delete[]
的实现,因此您不必担心调用者中的元素数量。但是,您也无法查询要使用它们的元素数量。如果你需要元素的数量,你也必须返回它们,也许是通过“out参数”。
在现代C ++中,我强烈建议使用与原始数组不同的数据结构,例如std::vector
,或std::map
如果需要 associative 容器,以及诸如“谁删除这个分配的内存?”之类的问题。走了。
答案 2 :(得分:0)
如果上面两个是p,那么在p上使用delete []会导致未定义的行为 真?
不,不删除[] p会导致内存泄漏!
然而,删除[] 神奇地知道数组有多长,sizeof(p)没有, 因为分配器跟踪分配的空间。但是sizeof是在编译时生成的固定值