0

我创建了一个测试类(tc),它包含一个指向 int 的数组指针。

class TC
{
public:
    int **values;
    TC(){values = new int*[10];
 };

当我实例化一个实例并进行以下更改时:

TC *a = new TC();    
int **values = &*a->values;
int **oldvalues = values;
values = new int*[10];
values[0] = oldvalues[0];
...
values[9] = oldvalues[9];

delete [] oldvalues;

for(int i = 0; i < 10; i++){
    delete values[i];
}

delete [] values;

现在是有趣的部分:

values = new int*[10];
*a->values = *values;

values[0] = new int(1);
values[9] = new int(10);
std::cout << *values[0] << " " << *values[9];

这打印出来

1 10

但是切换两条线

values = new int*[10];
*a->values = *values;

*a->values = *new int*[10];    
values = &*a->values;

印刷

182939382 10

第一部分是一些指针。

有人可以解释为什么会这样吗?两种处理指针的方法有什么区别?

编辑:我很感激建设性的意见。正如您可能会说的那样,我对 c++ 和指针处理没有任何经验。所以请帮助我理解我所犯的错误。

4

2 回答 2

4

这个

*a->values = *values;

是相同的

 a->values[0] = values[0];

但是values[0]未初始化,因此您不想从中读取。

于 2013-05-28T19:35:19.157 回答
1

如果这对您来说太长了,请跳到底部的tldr部分,但这不会帮助您理解问题,因为您需要阅读其余部分。


我的 c 生锈了,但有一些非常奇怪的部分:

让我们从这个开始:

TC *a = new TC();    
int **values = &*a->values;
int **oldvalues = values;
values = new int*[10];
values[0] = oldvalues[0];
...
values[9] = oldvalues[9];

delete [] oldvalues;

for(int i = 0; i < 10; i++){
    delete values[i];
}

delete [] values;

TC *a = new TC();    

非常好

int **values = &*a->values;

&*a->values;让我们一步一步看下半场

  a              //pointer to tc
  a->values      //access values member of the tc a points to
                 //this is a int**
 *a->values      //dereference the int**, so we have a int*  
&*a->values;     //get the address of int*, so we have int** again

简而言之,正如评论中所述,您可以编写a->values. 让我们进一步看,您似乎正在使用 int** 来保存指向 int 指针数组的指针。

现在int **values = a->values;归根结底是什么?您复制一个指针,这意味着**values现在a->values引用相同的地址(稍微偏离,但现在将数组视为指向第一个元素的指针,必须使用索引运算符延迟[],否则它们引用第一个元素) . 这意味着你指向同一个数组两次

values \ \ |- TC()创建的数组{values = new int*[10]; /a->值/

int **oldvalues = values;

基本上你创建了第三个指向同一个数组的指针,出于什么原因?

values = new int*[10];

在将其初始化 valuesa->values.

values[0] = oldvalues[0];
...
values[9] = oldvalues[9];

注意到您有两个指针,您现在可以复制数据。复制内存块的循环或函数可以缓解这种情况,但我推荐一个 stl 类,从 stl 中检查向量

delete [] oldvalues;

你 delete oldvalues,这是删除你的TC-Class 使用的数组。虽然需要删除使用 new 创建的内容,但这可能是地狱,如果TC'destructor也尝试删除数组(尽管不应delete为同一个对象多次调用)。此外,由于您的班级似乎假设这values是有效的,为什么不覆盖数组中的值呢?

for(int i = 0; i < 10; i++){
    delete values[i];
}
delete [] values;

你记得在删除数组之前删除所有整数,这很好,但为什么不覆盖它们呢?此外,这也应该由析构函数处理,如果你写一个(你应该)。但是有什么可疑的,你为什么复制元素,只是为了删除它们?

此外,为什么不使用整数数组?整数指针数组真的有必要吗?

这将是一个 int 数组 [1, 2, 3, 7]。虽然这是一个指针数组:[see 1, see 2, see 4, see 5],此外,在以下内存地址 1@1、2@2、3@4、7@5 处还有以下数字

对于指针数组,您必须执行以下操作才能获取数字:

*arrayOfPointers[3]

这将执行以下操作:

  1. 加载4th(用于索引从 0 开始计数)数组元素的值see 5
  2. 该值被取消引用,这意味着计算机查看带有标签 5 的内存位置并看到7

对于整数数组aarrayOfIntegers[3]就足够了,它可以节省一层间接性。


到最后一个片段:

values = new int*[10];

你创建一个数组来替换你刚刚删除的那个。

*a->values = *values;

您分配第一个元素,请参阅Ben Voigts 的回答并记住数组只是指向第一个元素的指针。因为你取消引用它,你复制第一个数组元素。您可以将这两行合二为一,并通过以下方式消除错误:

a->values = new int*[10];

回到你的代码:

values[0] = new int(1);
values[9] = new int(10);
std::cout << *values[0] << " " << *values[9];

你经历了所有这些麻烦,只是改变了第一个和最后一个数字....


TLDR,更短的解决方案

让我向您展示如何以更短的方式完成它:

类 TC { public: int *values; TC() : values(new int[10]) {} //google 初始化列表 ~TC(){ 删除值;} //析构函数,当你的实例需要清理时调用 };

用法:

TC *a = new TC();
a->values[0] = 1;
a->values[9] =10:
std::cout << a->values[0] << " " << a->values[9];

或没有指针

TC a();
a.values[0] = 1;
a.values[9] =10:
std::cout << a.values[0] << " " << a.values[9];
于 2013-05-28T22:29:26.340 回答