我无法理解此代码的结尾(array = 0;
):
#include <iostream>
int main()
{
std::cout << "Enter a positive integer: ";
int length;
std::cin >> length;
int *array = new int[length];
std::cout << "I just allocated an array of integers of length " << length << '\n';
array[0] = 5; // set element 0 to value 5
delete[] array; // use array delete to deallocate array
array = 0; // use nullptr instead of 0 in C++11
return 0;
}
最后,删除动态分配的数组(返回到OS),然后将其赋值为0.
为什么这样做?将数组返回到OS后,无需为其赋值0,对吗?
代码来自:http://www.learncpp.com/cpp-tutorial/6-9a-dynamically-allocating-arrays/
答案 0 :(得分:14)
将数组返回给操作系统后,无需为其赋值0,对吗?
你是对的,因为内存被operator delete
释放(释放),所以不需要它。但是想想在你使用delete[]
之后你可以在代码中的另一个地方(函数,循环等)使用指针的情况。
在调用array
语句(dangling pointer)后,delete[]
变量仍保留旧分配的地址。如果您访问该地址,您将获得undefined bahaviour (UB),因为内存不再是您的,在大多数情况下您的程序会崩溃。
为避免您执行null pointer检查,例如:
if (array != nullptr)
{
/* access array */
...
}
检查指针对地址0,表示无效地址。
如果C ++ 11不可用,则可以将指针设置为nullptr
或NULL
。 nullptr
关键字引入了类型安全性,因为它的作用类似于指针类型,应优先于类似C的NULL
。在预C ++ 11中,NULL
被定义为整数0,因为C ++ 11它是nullptr
的别名。
要定义自己的nullptr
以将其用于预C ++ 11编译器,请在此处查看:How to define our own nullptr in c++98?
有关delete
或delete[]
的一个有趣的事实是,在nullptr
上使用它是安全的。它写在cppreference.com上的第2点或SO answer处。
操作员删除,操作员删除[]
2) [...]此函数的标准库实现的行为是未定义的,除非
ptr
是空指针或者是先前从operator new[](size_t)
或运算符{{1}的标准库实现获得的指针}。
答案 1 :(得分:8)
我们设置指向NULL
(0)的指针以避免悬空指针(指针仍然指向不再属于你的相同内存)。在局部变量的情况下,如果函数在删除后没有继续(因此它的明显指针不会被重用),那么它就没那么有用了。如果是全球/成员poitners,它的良好做法是避免错误。
访问已删除的指针可能会导致覆盖/读取随机内存(可能比崩溃更危险)并导致undefined behavior,而访问NULL
指针会立即崩溃。
由于c++11您应该使用nullptr
,因为它定义为指针类型,而NULL
更多int
类型并提高了类型安全性+解决了模棱两可的情况。
如果双删除指针,可以安全地使用nullptr
上的删除,但没有任何反应,但是如果你删除已经删除的非空指针,它将导致undefined behavior,并且很可能程序将崩溃。
在c++中,您应该避免使用纯指针,因为有STL容器(可以自行释放资源(RAII))用于此用法或smart pointers。
std::vector<int> array{1,2,3,4,5};
答案 2 :(得分:3)
这样做是为了将指针设置为NULL
(无论是在C ++中,我们都预先nullptr,因为NULL
和0可能是不同的东西。)
这种策略消除了悬空指针的可能性,因为数组可能已被删除,但这并不意味着它被设置为NULL
。
如果我们不这样做,我们冒着检查指针是否为NULL
的风险(我们的代码中的后一个),我们会发现它不是{{1错误地认为指针可以被访问,并导致未定义的行为。
答案 3 :(得分:1)
您指定的值通常称为“无效地址”,即NULL
,0
或指针类型nullptr
,因为否则您无法知道您是否指针指向无效的地址。换句话说,当您delete[]
数组时,指针“不知道”它指向不再可用的内存地址。