指针数组无法解释的行为(带浅拷贝)c ++

时间:2016-12-07 04:37:11

标签: c++ arrays pointers

这是C ++(GNU GCC编译器)中指针数组的行为,我无法找到解释,希望有人可以清除这种混淆。

我正在创建一个指针数组(arr_ptr),指针指向有效数据,然后我创建另一个指针数组(arrcopy),我这样做 - 我认为 - 浅层副本(arrcopy = arr_ptr),我得到了预期的数据......到目前为止一直很好。

我不理解的部分是,在删除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是否仍然指向a,b,c数据值的内存位置? enter image description here

2 个答案:

答案 0 :(得分: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[],当向量超出范围时,内存会自动释放。

答案 1 :(得分:2)

arr_ptrarrcopy都不是数组。两者都只是指针。

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

在您的情况下,使用您在动态内存中分配的数组的地址初始化arr_ptr。但它也可以用堆栈中单个对象的地址初始化:

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

通过将该指针的值复制到同一类型的另一个指针中,您只需要两个指向相同内存位置的指针:

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