tags:

views:

744

answers:

6
+5  Q: 

Dynamic Arrays

I'm just starting to learn C++ so excuse me for this simple question. What I'm doing is reading in numbers from a file and then trying to add them to an array. My problem is how do you increase the size of the array? For example I thought might be able to just do:

#include <iostream>
using namespace std;

int main() {
    double *x;
    x = new double[1];
    x[0]=5;
    x = new double[1];
    x[1]=6;
    cout << x[0] << "," << x[1] << endl;
    return 0;
}

But this obviously just overwrites the value, 5, that I initially set to x[0] and so outputs 0,6. How would I make it so that it would output 5,6?

Please realize that for the example I've included I didn't want to clutter it up with the code reading from a file or code to get numbers from a user. In the actual application I won't know how big of an array I need at compile time so please don't tell me to just make an array with two elements and set them equal to 5 and 6 respectively.

Thanks for your help.

+15  A: 

You don't want to work with arrays directly. Consider using a vector, instead. Then, you can call the push_back function to add things to the end, and it will automatically resize the vector for you.

#include <iostream>
#include <vector>

int
main() {
    double value;
    std::vector<double> values;

    // Read in values
    while (std::cin >> value) {
        values.push_back(value);
    }

    // Print them back out
    for (std::size_t i(0), len(values.size()); i != len; ++i) {
        std::cout << values[i];
    }
}
Chris Jester-Young
You've got to be careful with vector's though, they tend to be pretty slow in usage.
Huppie
Slow is relative. i.e., profile your program and see if it impacts things. If it does, write a custom allocator, optimised for allocating doubles (and objects of size `sizeof (double)`).
Chris Jester-Young
It won't be any slower than doing the resizing yourself with new, delete, and copying.
Greg Rogers
@Chris Jester-Young it is indeed, and it is because I've been profiling a lot that I am warning, mind you I'm not saying vectors are bad ;-)
Huppie
@Greg: It will, this is because by default vectors check if an accessor (vector[index]) is inside the vector's range ('safe' as you will).
Huppie
+4  A: 

You should use a collection class to do this for you rather than managing it yourself. Have a look at the "vector" class. It's essentially a dynamic array that resizes automatically as required.

In your situation you would use "vector" with the "double" type. You may also need to read up on templates in C++.

http://www.cplusplus.com/reference/stl/vector/

Ty
+3  A: 

Or, if you don't want to use STL or another dynamic thing, you can just create the array with the correct size from the beginning: x = new double[2];

Of course the problem there is how big to make it. If you don't know, then you'll need to just create it "big enough" (like a hundred, or a thousand)... which, at some point, won't be big enough and it will fail in some random looking way. So then you'll need to resize it. And once you get to that point, you'll wish you'd used the STL from the start, like the other answers are telling you to do.

#include <iostream>
using namespace std;
int main() {
    double *x = new double[2];
    x[0]=5;
    x[1]=6;
    cout << x[0] << "," << x[1] << endl;
    return 0;
}
Mark Santesson
+2  A: 

If for some reason you don't have access to STL -- or want to learn how to do this yourself -- you could use an algorithm like this:

Allocate your array as some arbitrary size, and remember how many elements are in it and how big it is:

int *a = malloc(int * ARBITRARY_SIZE);
int size = 0;
int allocated = ARBITRARY_SIZE;

each time you add a new element, increase "size". If size equals ARBITRARY_SIZE, multiply 'allocated' by 2, and reallocate the array. Either way, assign the new value to a[size].

void addElement(int value) {
  ++size;

  if (size == allocated) {
    allocated *= 2;
    a = realloc(sizeof(int) * allocated);
    a = new_a;
  }

  a[size] = value;
}

Note that your code above has at least one bug -- you aren't allocating enough space for x[1] in either case.

Also obviously in real code you'd check that the return from malloc & realloc isn't null.

Moishe
It's also traditional to check the return value from malloc for null. Unlike new it doesn't throw std::bad_alloc on failure, and core dumps are harder to debug than failed asserts ;-)
Steve Jessop
Made changes.Though core dumps are much easier to debug than most other bugs :)
Moishe
+2  A: 

Here's an example though for good measure, so you can see the pattern:

#include <iostream>
using namespace std;

int main() {
    // Allocate some memory for a double array of size 1 and store
    // an address to the beginning of the memory in mem_address.
    double* mem_address = new double[1];

    // Assign 5 to the first element in the array.
    mem_address[0] = 5;

    // Save the address of the memory mem_address is currently
    // referencing.
    double* saved_address = mem_address;

    // Allocate some memory for a double array of size 2 and store
    // an address to the beginning of the memory in mem_address.
    mem_address = new double[2];

    // Copy over the 1 element from the first memory block
    // to the new one.
    mem_address[0] = saved_address[0];

    // Done with the old memory, so clean it up.
    delete [] saved_address;

    // Assign 6 to the second element in the new array.
    mem_address[1] = 6;

    // Print out the 2 elements in the new array.
    cout << mem_address[0] << "\n";
    cout << mem_address[1] << "\n";

    // Done with the new array memory now, so clean it up.
    delete [] mem_address;
}
Shadow2531
A: 

An array always needs a contiguous block of memory. In a situation where you might need to resize the array later on, reallocation is probably the only solution. This is what Moishe and Shadow2531 do above.

The problem with reallocation is that it can be a costly operation. So if you need adding 5 more elements to a 5000 element array, you might end up copying all the 5000 elements across memory.

Using a linked list instead can be considered for such a scenario.

Abhishek Yadav