简体   繁体   English

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

[英]Beginner C++ programmer, confused over dynamic arrays

I am trying to create a class analogous to the built-in vector class in C++. 我正在尝试创建一个类似于C ++中内置向量类的类。 I have tried to follow all the instructions in Walter Savitche's textbook, but just can't get it to work properly. 我尝试按照Walter Savitche教科书中的所有说明进行操作,但无法使其正常工作。

The code was written using the Code::Blocks IDE and compiled using the gcc compiler. 该代码是使用Code :: Blocks IDE编写的,并使用gcc编译器进行了编译。

The thing I think I'm missing is the relationship between array parameters and a pointer that points to an array. 我想我缺少的是数组参数和指向数组的指针之间的关系。 This is what I understand about normal variables: 这是我对普通变量的了解:

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

This is what I essentially don't understand about arrays and pointers that point to arrays 这基本上是我对数组和指向数组的指针不了解的内容

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?

For completeness sake my class is defined as follows: 为了完整起见,我的课程定义如下:

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
};

And the troublesome function is: 而且麻烦的功能是:

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;
}

The member function just seems to insert 0.0 instead of the user input, I have no idea why... 成员函数似乎只是插入0.0而不是用户输入,我不知道为什么...

In main: 在主要方面:

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;

I enter: 我输入:

12.5 16.8 15.2 12.5 16.8 15.2

I get back: 我回来了:

0 0 0 0 0 0

I fixed it! 我修好了它! Only problem is that the mistake was exceedinly simple. 唯一的问题是错误非常简单。 Sorry to waste everybodies time, but thanks to all, I did learn quite a lot! 抱歉浪费大家的时间,但多亏了,我确实学到了很多东西!

The mistake was my placement of amt_count += 1; 错误是我放置amt_count += 1; , I'm used to arrays indexed from 1 not zero (I have done a lot of coding in the R language). ,我习惯于从1而不是零开始索引的数组(我已经用R语言做了很多编码)。 The corrected code with the memoery leak taken care of is: 纠正了内存泄漏的更正代码是:

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;
}

This is what I understand about normal variables 这是我对普通变量的了解

All correct, with the caveat that I'd avoid the terminology "points to the value x "; 完全正确,但我要避免使用术语“指向值x ”的警告; you're pointing to the object , which in turn has value x . 您所指向的对象具有x值。

This is what I essentially don't understand about arrays and pointers that point to arrays 这基本上是我对数组和指向数组的指针不了解的内容

You're confusing pointers with arrays. 您正在将指针与数组混淆。 In int a[3] , a is an array. int a[3]a是一个数组。 It is not a pointer. 它不是指针。 It is an array. 它是一个数组。

*p3 = a isn't valid, so it means nothing. *p3 = a无效,因此没有任何意义。

p2 now points to p4, but what happens to the array p2 was pointing to? p2现在指向p4,但是p2指向的数组会发生什么?

You've leaked it. 你已经泄漏了。

// does this destroy the pointer and the array it is pointing to or just one or the other? //这会破坏指针和它所指向的数组还是一个或另一个?

It destroys the thing you new 'd, that the pointer is pointing to. 它破坏了你的东西new “d,指针指向。 ie the array 即数组

Otherwise all correct. 否则一切正确。


As for your vector implementation, the main problem is that temp[amt_count] is an overflow because you've already incremented amt_count . 至于向量实现,主要问题是temp[amt_count]溢出,因为您已经增加了amt_count Also, vector implementations typically grow exponentially rather than on-demand. 而且,矢量实现通常呈指数增长,而不是按需增长。 Finally, you're leaking the previous storage. 最后,您正在泄漏先前的存储。

Using different terminology might help you: 使用不同的术语可能会帮助您:

A pointer is just an ordinary variable. 指针只是一个普通变量。 Instead of holding an integer, a float, a double, etc., it holds a memory address. 它不保存整数,浮点数,双精度数等,而保存一个内存地址。 Consider the following: 考虑以下:

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

The ampersand gets the address of a variable. “&”号获取变量的地址

An asterisk dereferences a pointer; 星号取消引用指针; that is it will get the value stored in the memory address the pointer holds: 那就是它将获取存储在指针所拥有的内存地址中的值:

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

As for your vector implementation, try moving this line amt_count += 1; 至于您的向量实现,请尝试将这行移动amt_count += 1; to below this line: temp[amt_count] = put_at_end; 到此行以下: temp[amt_count] = put_at_end; , as you're trying to access beyond the end of your array. ,因为您尝试访问数组末尾之外的内容。


Most of your understanding is correct. 您的大多数理解是正确的。 But... 但...

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

Although arrays and pointers can be indexed and treated in a similar fashion, they are different, and their differences can lead to some sneaky bugs; 尽管可以用相似的方式对数组和指针进行索引和处理,但是它们是不同的,它们之间的差异可能会导致一些偷偷摸摸的错误。 so be careful with this statement. 因此,请谨慎使用此声明。

*p3 = a // what does this mean?

This is invalid. 这是无效的。 Your types don't match: *p3 is an integer, a is an array. 您的类型不匹配:* p3是整数,a是数组。

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

The array p2 was pointing to is now leaked memory. p2指向的数组现在是内存泄漏。 This is bad. 这不好。

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

The value of the pointer does not change. 指针的值不变。 However, the memory it points to is deallocated, so dereferencing it will give you undefined results. 但是,它指向的内存已释放,因此取消引用它会给您未定义的结果。 It's best to set p2 = nullptr; 最好设置p2 = nullptr; after deleting it. 删除后。

This answer might help with your understanding of arrays and accessing their elements. 该答案可能有助于您理解数组并访问它们的元素。

Your function is really wrong... 您的功能确实有误...

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;
}

Notice that in each call you allocate new array (even if there's still space), copy everything in it and leak memory (old array)... 请注意,在每个调用中,您分配新数组(即使还有空间),也要复制其中的所有内容并泄漏内存(旧数组)...

Here is a slightly corrected version, but it's not guaranteed to be completely OK (; 这是一个经过更正的版本,但不能保证完全正确(;

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;
}

"p2 now points to p4, but what happens to the array p2 was pointing to?" “ p2现在指向p4,但是p2指向的数组会发生什么?”

It is 'leaked', this means its still allocated but there is no way to reach it anymore. 它已“泄漏”,这意味着它仍在分配中,但再也无法实现。 If you keep doing this is the same program your memory size will keep growing 如果您继续执行同一程序,则内存大小将继续增长

Other languages (Java, c#,...) have 'garbage collectors' that detect when this happens and will free the memory automatically 其他语言(Java,c#,...)具有“垃圾收集器”,它们可以检测何时发生并自动释放内存

C++ solution to this problem is to never user naked arrays and pointers. C ++解决此问题的方法是永远不要使用裸数组和指针。 Instead you use std::vector and std::shared_ptr; 相反,您使用std :: vector和std :: shared_ptr; these will clean up for you 这些会为你清理

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM