2017-08-28 98 views
7

我无法理解此代码的末尾(array = 0;):删除动态分配的变量设定指针为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.

为什么这样做?数组返回到操作系统后,没有必要为它赋值0,对吧?从

代码:http://www.learncpp.com/cpp-tutorial/6-9a-dynamically-allocating-arrays/

+1

它设置一个有效的(但为空)指向数组的指针,以避免有悬挂指针。所以稍后,我们可以在使用之前测试'array'。如果指针不再使用,则确实不需要。 – Jarod42

+0

int *数组作为一个指针,即使解除了对象的分配,仍然保留它指向的地址的信息。由于该空间不再属于该指针,因此将其设置为0,以便您不能访问某些随机数据。 – metamorphling

+2

使用'std :: vector'可以避免那些手动的内存管理。 – Jarod42

回答

15

将数组返回给操作系统后,不需要为它赋值0,对不对?

你说得对,因为内存被释放(释放)了operator delete。但想一想在你使用delete[]之后,你可以在你的代码的另一个地方(函数,循环等)使用指针的情况。

array变量在delete[]声明被称为(dangling pointer)后仍然保留旧分配的地址。如果你要访问该地址,你会得到undefined bahaviour (UB),因为内存不再是你的,在大多数情况下你的程序会崩溃。

为避免你做一个null pointer检查,如:

if (array != nullptr) 
{ 
    /* access array */ 
    ... 
} 

这是检查,对代表的无效地址地址0的指针。

要使检查成为可能,请将指针设置为nullptrNULL如果C++ 11不可用。 nullptr关键字引入了类型安全性,因为它的行为类似于指针类型,应该优于类似C的NULL。在pre C++ 11中NULL被定义为整数0,因为C++ 11它是nullptr的别名。
要定义自己nullptr使用它的前C++编译器11看这里:How to define our own nullptr in c++98?


一个有趣的事实有关deletedelete[]的是,它是安全的使用上nullptr。它写在cppreference.com的第2点或这个SO answer

操作者删除,操作者删除[]

2) [...]的标准库实现此功能的行为是不确定的,除非ptr是空指针或在先前的指针从标准库实现operator new[](size_t)或运营商new[](size_t, std::nothrow_t)获得。

+3

是的,**如果你的设计需要重用指针,那么你需要一个标志来告诉你指针不指向有效的东西;这是一个空指针的用途。它应该**不会**在删除之后自动使用。特别是,编写一个析构函数是愚蠢的,它会删除一个已分配的块,然后将指针设置为null,但这在初学者的代码中经常出现。 –

+1

@PeteBecker为什么会这么傻?在以后使用重复使用的情况下,是否总是在删除后清空指针?缺点是什么? – Sossisos

+1

@Sossisos - 这是**愚蠢**的原因是,析构函数运行后,对象**不存在**,并且**没有指针**可重用。缺点是它使得编写代码的人看起来像是用口号代码而不是思考。 –

3

这样做,使得指针被设置为NULL(无论是在C++中,我们preffer nullptr,由于NULL和0可以是不同的东西)。

这种策略消除了悬挂指针的可能性,因为该数组可能已被删除,但这并不意味着它被设置为NULL

如果我们不这样做,我们冒着检查指针是否为NULL的风险(在我们的代码中后者),我们将看到它不是NULL,错误地认为指针可以被访问,并导致未定义的行为。

+0

它应该设置为nullptr。在C++ nullptr中,NULL和0是不同的东西 –

+0

@ArtemyVysotsky好点,回答更新。 – gsamaras

8

我们正在设置指针NULL(0)以避免悬挂指针(指针仍然指向不再是你的同一内存)。在局部变量的情况下,如果函数在删除后不继续,那么它就没有用处(所以它的明显指针将不会被重用)。如果全球/会员poitners避免错误的良好做法。

访问已经删除的指针可能会导致覆盖/读取随机内存(它可能比崩溃更危险),并导致undefined behavior,而访问NULL指针将立即崩溃。

由于你应该使用nullptr,因为它定义为指针类型,而NULLint型和改善型安全+解析模糊的情况。

在双删除指针的情况下,其安全使用nullptr上的删除并没有任何反应,但如果删除已删除的非空指针,将导致undefined behavior,最有可能的程序将崩溃。

你应该避免使用纯指针,因为STL容器(这可以释放它们自己的资源(RAII))或smart pointers

std::vector<int> array{1,2,3,4,5}; 
+1

回复:“避免错误的良好做法” - 避免错误的最佳做法是**设计**代码并**实施**设计。自动设置指针为空_just,以防有人不小心做**不**避免bug; **设计**和**实现**使用null来表示指针指向无效的系统。 –

1

分配给俗称“无效地址”,即NULL0或指针类型nullptr的值,否则没有办法,你可以知道你是否指针指向的地址无效。换句话说,当你的数组delete[]你的数组指针“不知道”它指向一个不再可用的内存地址。