I can use pointers, but I am a bit afraid of using them.
If you need a dynamic array, you can't escape pointers. Why are you afraid though? They won't bite (as long as you're careful, that is). There's no built-in dynamic array in C, you'll just have to write one yourself. In C++, you can use the built-in std::vector class. C# and just about every other high-level language also have some similar class that manages dynamic arrays for you.
If you do plan to write your own, here's something to get you started: most dynamic array implementations work by starting off with an array of some (small) default size, then whenever you run out of space when adding a new element, double the size of the array. As you can see in the example below, it's not very difficult at all: (I've omitted safety checks for brevity)
typedef struct {
int *array;
size_t used;
size_t size;
} Array;
void initArray(Array *a, size_t initialSize) {
a->array = malloc(initialSize * sizeof(int));
a->used = 0;
a->size = initialSize;
}
void insertArray(Array *a, int element) {
// a->used is the number of used entries, because a->array[a->used++] updates a->used only *after* the array has been accessed.
// Therefore a->used can go up to a->size
if (a->used == a->size) {
a->size *= 2;
a->array = realloc(a->array, a->size * sizeof(int));
}
a->array[a->used++] = element;
}
void freeArray(Array *a) {
free(a->array);
a->array = NULL;
a->used = a->size = 0;
}
Using it is just as simple:
Array a;
int i;
initArray(&a, 5); // initially 5 elements
for (i = 0; i < 100; i++)
insertArray(&a, i); // automatically resizes as necessary
printf("%d\n", a.array[9]); // print 10th element
printf("%d\n", a.used); // print number of elements
freeArray(&a);
Answer from casablanca on Stack OverflowI can use pointers, but I am a bit afraid of using them.
If you need a dynamic array, you can't escape pointers. Why are you afraid though? They won't bite (as long as you're careful, that is). There's no built-in dynamic array in C, you'll just have to write one yourself. In C++, you can use the built-in std::vector class. C# and just about every other high-level language also have some similar class that manages dynamic arrays for you.
If you do plan to write your own, here's something to get you started: most dynamic array implementations work by starting off with an array of some (small) default size, then whenever you run out of space when adding a new element, double the size of the array. As you can see in the example below, it's not very difficult at all: (I've omitted safety checks for brevity)
typedef struct {
int *array;
size_t used;
size_t size;
} Array;
void initArray(Array *a, size_t initialSize) {
a->array = malloc(initialSize * sizeof(int));
a->used = 0;
a->size = initialSize;
}
void insertArray(Array *a, int element) {
// a->used is the number of used entries, because a->array[a->used++] updates a->used only *after* the array has been accessed.
// Therefore a->used can go up to a->size
if (a->used == a->size) {
a->size *= 2;
a->array = realloc(a->array, a->size * sizeof(int));
}
a->array[a->used++] = element;
}
void freeArray(Array *a) {
free(a->array);
a->array = NULL;
a->used = a->size = 0;
}
Using it is just as simple:
Array a;
int i;
initArray(&a, 5); // initially 5 elements
for (i = 0; i < 100; i++)
insertArray(&a, i); // automatically resizes as necessary
printf("%d\n", a.array[9]); // print 10th element
printf("%d\n", a.used); // print number of elements
freeArray(&a);
One simple solution involves mmap. This is great if you can tolerate a POSIX solution. Just map a whole page and guard against overflows, since realloc would fail for such values anyway. Modern OSes won't commit to the whole lot until you use it, and you can truncate files if you want.
Alternatively, there's realloc. As with everything that seems scarier at first than it was later, the best way to get over the initial fear is to immerse yourself into the discomfort of the unknown! It is at times like that which we learn the most, after all.
Unfortunately, there are limitations. While you're still learning to use a function, you shouldn't assume the role of a teacher, for example. I often read answers from those who seemingly don't know how to use realloc (i.e. the currently accepted answer!) telling others how to use it incorrectly, occasionally under the guise that they've omitted error handling, even though this is a common pitfall which needs mention. Here's an answer explaining how to use realloc correctly. Take note that the answer is storing the return value into a different variable in order to perform error checking.
Every time you call a function, and every time you use an array, you are using a pointer. The conversions are occurring implicitly, which if anything should be even scarier, as it's the things we don't see which often cause the most problems. For example, memory leaks...
Array operators are pointer operators. array[x] is really a shortcut for *(array + x), which can be broken down into: * and (array + x). It's most likely that the * is what confuses you. We can further eliminate the addition from the problem by assuming x to be 0, thus, array[0] becomes *array because adding 0 won't change the value...
... and thus we can see that *array is equivalent to array[0]. You can use one where you want to use the other, and vice versa. Array operators are pointer operators.
malloc, realloc and friends don't invent the concept of a pointer which you've been using all along; they merely use this to implement some other feature, which is a different form of storage duration, most suitable when you desire drastic, dynamic changes in size.
It is a shame that the currently accepted answer also goes against the grain of some other very well-founded advice on StackOverflow, and at the same time, misses an opportunity to introduce a little-known feature which shines for exactly this usecase: flexible array members! That's actually a pretty broken answer... :(
When you define your struct, declare your array at the end of the structure, without any upper bound. For example:
struct int_list {
size_t size;
int value[];
};
This will allow you to unite your array of int into the same allocation as your count, and having them bound like this can be very handy!
sizeof (struct int_list) will act as though value has a size of 0, so it'll tell you the size of the structure with an empty list. You still need to add to the size passed to realloc to specify the size of your list.
Another handy tip is to remember that realloc(NULL, x) is equivalent to malloc(x), and we can use this to simplify our code. For example:
int push_back(struct int_list **fubar, int value) {
size_t x = *fubar ? fubar[0]->size : 0
, y = x + 1;
if ((x & y) == 0) {
void *temp = realloc(*fubar, sizeof **fubar
+ (x + y) * sizeof fubar[0]->value[0]);
if (!temp) { return 1; }
*fubar = temp; // or, if you like, `fubar[0] = temp;`
}
fubar[0]->value[x] = value;
fubar[0]->size = y;
return 0;
}
struct int_list *array = NULL;
The reason I chose to use struct int_list ** as the first argument may not seem immediately obvious, but if you think about the second argument, any changes made to value from within push_back would not be visible to the function we're calling from, right? The same goes for the first argument, and we need to be able to modify our array, not just here but possibly also in any other function/s we pass it to...
array starts off pointing at nothing; it is an empty list. Initialising it is the same as adding to it. For example:
struct int_list *array = NULL;
if (!push_back(&array, 42)) {
// success!
}
P.S. Remember to free(array); when you're done with it!
How common are dynamic arrays in C?
Creation of Dynamic Array of Dynamic Objects in C++ - Stack Overflow
Create a dynamic array within a class (C++) - Stack Overflow
c++ - Dynamic arrays inside a class - Stack Overflow
Videos
I feel like every solution I code up, I end up implementing a dynamic array/arraylist/whatever you wanna call it. For some reason I think this is a bad thing?
If you are using c++ then you shouldn't reinvent the wheel, just use vectors:
#include <vector>
std::vector< std::vector< Stock > > StockVector;
// do this as many times as you wish
StockVector.push_back( std::vector< Stock >() );
// Now you are adding a stock to the i-th stockarray
StockVector[i].push_back( Stock() );
Edit:
I didn't understand your question, if you just want to have and array of arrays allocated on the heap just use:
Stock** StockArrayArray = new Stock*[n]; // where n is number of arrays to create
for( int i = 0; i < n; ++i )
{
StockArrayArray[i] = new Stock[25];
}
// for freeing
for( int i = 0; i < n; ++i )
{
delete[] StockArrayArray[i];
}
delete[] StockArrayArray;
The type of a variable to a dynamic array is a pointer to the first object of the array. You want an array of dynamically allocated Stock objects, so an array of pointers to Stock, so your variable is a pointer to a pointer to Stock:
int n = 4; // dynamic size of the array;
Stock** stockArray = new Stock*[n];
for (int i = 0; i != n; ++i)
{
stockArray[i] = new Stock();
}
and freeing it:
for (int i = 0; i != n; ++i)
{
delete stockArray[i];
}
delete[] stockArray;
Use std::vector. C++ doesn't support variable-length or dynamically-sized arrays, in classes or otherwise.
Use a std::vector and let it manage everything for you:
#include <vector>
class ArrayList
{
public:
ArrayList()
{
array.reserve(ARR_SIZE);
}
void insert(int place, int value)
{
if ((place < 0) || (place > array.size()))
std::cout << "Sorry, that index is not accessible" << std::endl;
else
array.insert(array.begin()+place, value);
}
void remove(int place)
{
if ((place < 0) || (place >= array.size()))
std::cout << "Sorry, that index is not accessible" << std::endl;
else
array.erase(array.begin()+place);
}
int usedSize()
{
return array.size();
}
int totalSize()
{
return array.capacity();
}
private:
std::vector<int> array;
};
If you really want to manage the array memory yourself, you are doing it all wrong. Try this instead:
class ArrayList
{
public:
ArrayList()
{
array = new int[ARR_SIZE];
space = 0;
size = ARR_SIZE;
}
ArrayList(const ArrayList &src)
{
array = new int[src.size];
space = src.space;
size = src.size;
for(int i = 0; i < space; ++i)
array[i] = src.array[i];
}
~ArrayList()
{
delete[] array;
}
void insert(int place, int value)
{
if ((place < 0) || (place > space))
std::cout << "Sorry, that index is not accessible" << std::endl;
else
{
if (space == size)
allocate();
for(int i = space-1; i > place; --i)
array[i] = array[i-1];
array[place] = value;
++space;
}
}
void remove(int place)
{
if ((place < 0) || (place >= space))
std::cout << "Sorry, that index is not accessible" << std::endl;
else
{
for(int i = place+1; i < space; ++i)
array[i-1] = array[i];
--space;
}
}
void allocate()
{
int* newarray = new int[size*2];
for (int i = 0; i < space; ++i)
newarray[i] = array[i];
delete[] array;
array = newarray;
size *= 2;
}
int usedSize()
{
return space;
}
int totalSize()
{
return size;
}
ArrayList& operator=(const ArrayList &src)
{
int *newarray = new int[src.size];
for(int i = 0; i < src.space; ++i)
newarray[i] = src.array[i];
delete[] array;
array = newarray;
space = src.space;
size = src.size;
return *this;
}
private:
int *array;
int space;
int size;
};
In your constructors, you're defining a local variable
double * matrix = new double[N * N];
which shadows your member variable of the same name, so the member is never initialised.
All you should need is to change it to
matrix = new double[N * N];
And it's very un-C++ to use this-> for member access unless it's absolutely necessary for disambiguation (which is almost never)
You will find more "C++" (and sometime the only way to initialize members):
Matrix::Matrix(int M, int N): rows (M),
columns (N),
matrix (new double[M * N])
{
for(int i = 0; i < M; i++)
for(int j = 0; j < N; j++)
matrix[i * N + j] = 0;
}
Now try to understand this:
Matrix::Matrix( int N): rows (N),
columns (N),
matrix (new double[N * N])
{
for(int i = 0; i < N; i++)
for(int j = 0; j < N; j++)
matrix[i * N + j] = (i==j);
}
If you use:
class Matrix{
private:
int rows;
int columns;
std::unique_ptr<double[]> matrix;
you will find that you dont need a destructor, and some other inerest thing. Also, read my other answer.
There are multiple issues with your code! Starting with a minor one in the copy constructor: if new T[n] fails, it does not return 0. Instead, it throws and exceptions. Thus, your test if (!ptr) will never be reached. In your code it would be too late anyway as you already used the pointer!
The assignment operator is entirely garbled! The use of a self-assignment check is generally a very good indication that the code is not exception safe (if self-assignment genuinely wouldn't work without this check) or that you are optimizing for a rare case (hopefully you don't assign objects to themselves more often than to other objects). In your case the check indicates that the code, if it were working, would not be exception safe: You start off deleting memory which you can't get back if allocating memory fails and throws. The main error probably causing you grief is that you allocate numElements objects (which seems to be the number of elements in your array, not its capacity) but you copy size objects (which seems to be the number of possibly available elements, i.e., numElements < size). As a side note, I strongly recommend you use the same names as the standard C++ library does for its containers, i.e., size() for the number of actual elements and capacity() for the number of elements for which space is reserved.
All that said, the best approach to implementing the assignment operator is to leverage the work already done for the copy constructor and the destructor: these already know how to copy an object and how to get rid of the object. The way to do this looks like this:
Array& Array::operator= (Array other) {
this->swap(other);
return *this;
}
void Array::swap(Array& other) {
std::swap(this->ptr, other.ptr);
std::swap(this->size, other.size);
std::swap(this->numElements, other.numElements);
}
This approach requires that there is also a function swap() which can swap two objects of the type. However, it is typically trivial to write: you just std::swap() each of the members.
Your code breaks using insertValueAtEnd() because it does not grow the size of the underlying array. It crashed for me with this simple test case:
int realarr[] = { 1,2,3};
Array arr1(realarr, 3);
arr1.insertValueAtEnd(7);
You need to check if you have reached capacity (you call it size) and grow underlying storage if so.
I am assuming you are implementing a dynamic array?
Just a style issue you can ignore if you like. It is more common to use name_ as class data members and pass in name as a parameter.
new int(10) makes an int variable with the value 10. new int[10] makes an array of 10 ints. From the context, it's clear that you intended to use the second form. The use of the first form would lead to undefined behavior when you called delete[] values; (since values would not be an array) or when you accessed any elements beyond the first.
When you're allocating arrays you should do int *newvalues = new int[ntests+1]; using brackets instead []