2016-12-07 81 views
2

这是C++(GNU GCC编译器)中的指针数组的行为,我找不到解释,希望有人可以清除混淆。我创建了一个指针数组(arr_ptr),指针指向有效数据,然后创建另一个指针数组(arrcopy),我做了 - 我想 - 浅拷贝(arrcopy = arr_ptr) ,并且我得到了预期的数据...迄今为止非常好。指针数组无法解释的行为(与浅拷贝)C++

我不理解的部分是,在我删除arr_ptr后,不应该arrcopy仍然指向我的有效数据?为什么这不会发生? 谢谢。

int main() 
{ 
    int a = 1; int b=2; int c=3; 
    int* ap = &a; int* bp = &b; int* cp = &c; 

    // Array of pointers 
    int** arr_ptr = new int*[3]; 
    arr_ptr[0] = ap; 
    arr_ptr[1] = bp; 
    arr_ptr[2] = cp; 

    //shallow copy 
    int** arrcopy = arr_ptr; 

    cout << "Values: " << *(arr_ptr[0]) << " " << *(arrcopy[0]) << endl; 
    cout << "Addresses: " << arr_ptr[0] << " " << arrcopy[0] << endl; 
    cout << endl; 

    a++; 

    cout << "After Incrementing a:" << endl; 
    cout << *(arr_ptr[0]) << " " << *(arrcopy[0]) << endl; 
    cout << arr_ptr[0] << " " << arrcopy[0] << endl; 
    cout << endl; 

    *(arr_ptr[0]) = 5; 

    cout << "After updating a value to 5:" << endl; 
    cout << *(arr_ptr[0]) << " " << *(arrcopy[0]) << endl; 
    cout << arr_ptr[0] << " " << arrcopy[0] << endl; 
    cout << endl; 

    //so far so good - works as expected 

    //deleting arr_ptr 
    delete[] arr_ptr; 

    // Why?: shouldn't arrcopy still be pointing to A 
    cout << "Values: " << *(arr_ptr[0]) << " " << *(arrcopy[0]) << endl; //The result I am expecting here is: unknown_value 5 
    cout << "Addresses: " << arr_ptr[0] << " " << arrcopy[0]; 
    cout << endl; 


    return 0; 
} 

arr_ptr Initialization

后arr_ptr浅拷贝到arrcopy(arrcopy = arr_ptr) enter image description here

删除arr_ptr之后,不应该arrcopy仍然被指向的存储器位置,b,c数据值?! enter image description here

+0

'delete []'运算符还调用数组中所有元素的析构函数。我认为你的意思是一个简单的'删除'? –

+1

'arrcopy = arr_ptr'表示您有2个指向*相同数组*的指针。通过一个指针删除数组,而对另一个无效。 – Galik

+1

您没有制作数组的副本,只是将指针复制到数组。 – Galik

回答

3

您不必分配后2个数组,你有2个指向同一个数组:

arr_ptr -------->|ptr0|ptr1|ptr2|ptr3... (allocated memory) 


arr_cpy = arr_ptr; // copy only the pointer 

现在指针指向同一分配的内存

arr_ptr -------->|ptr0|ptr1|ptr2|ptr3... 
       ^
arr_cpy -----------| 


delete[] arr_ptr; // invalidate the memory that both pointers point to 

这给出:

arr_ptr -------->|xxx0|xxx1|xxx2|xxx3... (invalid memory) 
       ^
arr_cpy -----------| 

不要紧,你叫delete[]上,他们其中的指针都指向分配内存的同一块这样的电话后,他们都指向的同一块无效内存。

你需要做的就是复制整个数组:

int** arr_cpy = new int*[3]; 
std::copy(arr_ptr, arr_ptr + 3, arr_cpy); // copy the pointers to the new array 

或者好得多使用std::vector

int main() 
{ 
    int a = 1; int b=2; int c=3; 
    int* ap = &a; int* bp = &b; int* cp = &c; 

    // Array of pointers 
    std::vector<int*> arr_ptr{3}; 
    arr_ptr[0] = ap; 
    arr_ptr[1] = bp; 
    arr_ptr[2] = cp; 

    //shallow copy 
    std::vector<int*> arr_cpy = arr_ptr; // copy the whole vector 

    // ... etc. 

无需delete[],内存会自动释放,当你的载体超出范围。

2

​​也不是arrcopy是一个数组。两者都只是指针。

C++指针有点过载。它可以指向单个对象或指向一组对象。

在你的情况下,​​用你在动态存储器中分配的数组地址进行初始化。但是,它可能也有单个对象的栈上的地址进行初始化:

int i = 0; 
int** arr_ptr = &i; 

通过复制该指针的值转换为相同类型的另一个指针,你只需两个指针指的是同一个内存位置:

   // array in the heap 
       [xxxxxxxxxxxxxxxxxxxxxxx] 
      ^
      /\ 
      / \ 
     / \ 
     arr_ptr arrcopy