初学者C ++程序员,对动态数组感到困惑

时间:2014-11-21 17:03:49

标签: c++ arrays class pointers vector

我正在尝试创建一个类似于C ++中内置向量类的类。我试图遵循Walter Savitche的教科书中的所有说明,但却无法让它正常工作。

代码是使用Code :: Blocks IDE编写的,并使用gcc编译器编译。

我认为我缺少的是数组参数和指向数组的指针之间的关系。 这是我对正常变量的理解:

int *p1, *p2, *p3, *p4, a;
a = 5; // variable  of type int with value 5
p1 = &a; // p1 now points to the value 5
p2 = p1; // p2 now also points to the value of a
p3 = new int; // p3 points to an anonamous variable of type int with undefined value
*p3 = *p1 // value of variable changed to the value of a, namely 5, but doesn't point to a
p4 = new int; // p4 points to an anonamous variable of type int with undefined value
*p4 = 5; // value of variable changed to  5
p4 = p1 // p4 now also points to the value of a

这是我基本上不了解指向数组的数组和指针

int *p1, *p2, *p3, *p4, a[3] = {4, 5, 6}; // a points to the first indexed element of the array, namely 4
p1 = a; // p1 points to the exactly the same thing as a
p2 = new int[3]; // p2 points to an array of base type int with undefined values
p2[0] = 8; // is this the correct usage? is p2 "dereferenced" 
p2[1] = 9;
p2[2] = 10;
p2[2] = p1[2]; // again is this correct? is the third element of the array pointed to by p2 now equal to 6?
*p3 = a // what does this mean?
p4 = new int[4]; // p4 points to an array of base type int with undefined values
p4[0] = p2[0]; 
p4[1] = p2[1];
p4[2] = p2[2];
p4[3] = 3
p2 = p4 // p2 now points to p4, but what happens to the array p2 was pointing to?
delete [] p2; // does this destroy the pointer and the array it is pointing to or just one or the other?

为了完整起见,我的课程定义如下:

class VectorDouble
{
public:
    // constructors
    VectorDouble(); // default constructor
    VectorDouble(int init_count); // user specified
    VectorDouble(const VectorDouble& vd_object); // copy constructor
    // destructor
    ~VectorDouble();
    // accessors
    int capacity_vd(); // get max_count
    int size_vd(); // get amt_count
    double value_at(int index); // get value of "value" at index i
    // mutators
    void push_back_vd(double put_at_end); // insert new element at end of "value"
    void reserve_vd(int incr_capacity); // set max_count
    void resize_vd(int incr_size); // set amt_count
    void change_value_at(double d, int index); // set value of "value" at index i
    // overloaded =
    void operator =(const VectorDouble& vd_object_rhs);
    // other
    friend bool operator ==(VectorDouble vd_object1, VectorDouble vd_object2);
private:
    double *value; // pointer that points to array of type double
    int max_count; // the memory allocated to the array
    int amt_count; // the amount of memory in use
};

麻烦的功能是:

void VectorDouble::push_back_vd(double put_at_end)
{
    double *temp;
    if(amt_count == max_count)
        max_count += 1;
    temp = new double[max_count];
    for(int i = 0; i < amt_count; i++)
        temp[i] = value[i];
    amt_count += 1;
    temp[amt_count] = put_at_end;
    value = temp;
}

成员函数似乎只是插入0.0而不是用户输入,我不知道为什么......

主要:

VectorDouble vec1(10);
    double dd;

    cout << "Enter 3 doubles to vec1:\n";
    for(int i = 0; i < 3; i++)
    {
        cout << i << ": ";
        cin >> dd;
        vec1.push_back_vd(dd);
    }

    cout << "The variables you entered were:\n";
    for(int i = 0; i < 3; i++)
        cout << i << ": " << vec1.value_at(i) << endl;

我输入:

12.5 16.8 15.2

我回来了:

0 0 0

我修好了!唯一的问题是错误非常简单。很抱歉浪费每一个人的时间,但多亏了所有,我确实学到了很多东西!

错误是我放置amt_count += 1;,我习惯于从1开始索引的数组而不是零(我在R语言中做了很多编码)。纠正密码泄漏的纠正代码是:

void VectorDouble::push_back_vd(double put_at_end)
{
    double *temp;
    if(amt_count == max_count)
        max_count += 1;
    temp = new double[max_count];
    for(int i = 0; i < amt_count; i++)
        temp[i] = value[i];
    temp[amt_count] = put_at_end;
    amt_count += 1;
    delete [] value;
    value = temp;
}

4 个答案:

答案 0 :(得分:1)

  

这是我对正常变量的理解

一切都正确,但需要注意的是我要避免使用术语“指向值 x ”;您指向对象,而对象又具有值 x

  

这是我基本上不了解指向数组的数组和指针

你把指针与数组混淆了。在int a[3]中,a是一个数组。它不是指针。这是一个数组。

*p3 = a无效,所以没有任何意义。

  

p2现在指向p4,但是数组p2发生了什么指向?

你已经泄露了它。

  

//这是否会破坏指针及其指向的数组或只是其中一个?

它会摧毁指针所指向的new'。即阵列

否则一切正确。


至于你的矢量实现,主要问题是temp[amt_count]是一个溢出因为你已经增加了amt_count。此外,矢量实现通常以指数方式而非按需方式增长。最后,你正在泄漏以前的存储空间。

答案 1 :(得分:1)

使用不同的术语可能会对您有所帮助:

指针只是一个普通变量。它不包含整数,浮点数,双精度等,而是保存内存地址。请考虑以下事项:

int* p = nullptr; // p has the value "nullptr" or null memory address
int i = 5;        // i has value 5

p = &i;           // p now has the value of the address of i

&符号获取变量的地址

星号取消引用指针;也就是说,它将获得存储在指针所占用的内存地址中的值:

cout << *p << endl; // Prints whatever is stored in the memory address of i; 5

对于矢量实现,请尝试将此行amt_count += 1;移到此行下方: temp[amt_count] = put_at_end;,因为您尝试访问数组末尾。


您的大部分理解都是正确的。但是...

a[3] = {4, 5, 6}; // a points to the first indexed element of the array, namely 4

尽管可以以类似的方式对数组和指针进行索引和处理,但它们是不同的,它们之间的差异可能导致一些偷偷摸摸的错误;所以要小心这句话。

*p3 = a // what does this mean?

这是无效的。您的类型不匹配:* p3是整数,a是数组。

p2 = p4 // p2 now points to p4, but what happens to the array p2 was pointing to?

数组p2指向的是现在泄露的内存。这很糟糕。

delete [] p2; // does this destroy the pointer and the array it is pointing to or just one or the other?

指针的值不会改变。但是,它指向的内存已被释放,因此取消引用它将为您提供未定义的结果。删除后最好设置p2 = nullptr;

This answer可能有助于您理解数组并访问其元素。

答案 2 :(得分:0)

你的功能真的错了......

void VectorDouble::push_back_vd(double put_at_end)
{
    double *temp;
    if(amt_count == max_count)
        max_count += 1;
    temp = new double[max_count];
    for(int i = 0; i < amt_count; i++)
        temp[i] = value[i];
    amt_count += 1;
    temp[amt_count] = put_at_end;
    value = temp;
}

请注意,在每次调用中,您都会分配新数组(即使还有空格),复制其中的所有内容并泄漏内存(旧数组)......

这是一个略微更正的版本,但不能保证完全没问题(;

void VectorDouble::push_back_vd(double put_at_end)
{
    if(amt_count == max_count)
    {
        max_count += 1;
        double *temp = new double[max_count];
        for(int i = 0; i < amt_count; i++)
            temp[i] = value[i];
        delete[] value;
        value = temp;
    }
    value[amt_count] = put_at_end;
    amt_count += 1;
}

答案 3 :(得分:0)

“p2现在指向p4,但是数组p2发生了什么指向?”

它已“泄露”,这意味着它仍然已分配,但无法再进入它。如果你继续这样做是同一个程序你的内存大小将继续增长

其他语言(Java,c#,...)有'垃圾收集器',可以检测何时发生这种情况并自动释放内存

这个问题的C ++解决方案是永远不会使用裸数组和指针。相反,你使用std :: vector和std :: shared_ptr;这些将为你清理