Array of Pointers - c++

How can I get an array of pointers pointing to objects (classes) ?
I need to dynamically allocate space for them and the length of array isn't determined until run-time. Can any one explain and tell me how to define it? and possibly explain them how it works, would be really nice :)

Use std::vector instead. It's designed to dynamically resize the collection as needed.
#include <vector>
// ...
std::vector<Class*> vec;
vec.push_back(my_class_ptr);
Class* ptr = vec[0];

You can do this with a pointer to pointer to your class.
MyClass ** arrayOfMyClass = new MyClass*[arrayLengthAtRuntime];
for (int i=0;i<arrayLengthAtRuntime;++i)
arrayOfMyClass[i] = new MyClass(); // Create the MyClass here.
// ...
arrayOfMyClass[5]->DoSomething(); // Call a method on your 6th element
Basically, you're creating a pointer to an array of references in memory. The first new allocates this array. The loop allocates each MyClass instance into that array.
This becomes much easier if you're using std::vector or another container that can grow at whim, but the above works if you want to manage the memory yourself.

Use boost::ptr_vector and forget both array and pointer headaches:
boost::ptr_vector<animal> vec;
vec.push_back( new animal );
vec[0].eat();
You can add elements dynamically and you don't need to worry about deleting them.

I can't edit or comment yet so I have to post it in an answer: What Reed Copsey said, but with one fix. When you access elements of your array of pointers you need to access the members like this:
MyClass ** arrayOfMyClass = new MyClass*[arrayLengthAtRuntime];
for (int i=0;i<arrayLengthAtRuntime;++i)
arrayOfMyClass[i] = new MyClass(); // Create the MyClass here.
// ...
arrayOfMyClass[5]->DoSomething(); // Call a method on your 6th element
I use this method a lot to implement my own dynamic size arrays (what std::vector is), mostly because I have Not Invented Here syndrome but also because I like to customize them to my particular use.

Related

Can I pass a pointer to a pointer, allocate memory, then pass it back?

Consider the following code. This works for allocating a single array, but what if you needed to allocate a two dimensional array? How would you go about doing this?
#include <iostream>
void alloc(int **num)
{
*num = new int[5];
*num[0] = 5;
}
int main()
{
int *num;
alloc(&num);
std::cout << num[0] << std::endl;
delete [] num;
}
My goal is to pass **char into the function and have it allocated. Is this possible?
what if you needed to allocate a two dimensional array?
My goal is to pass **char into function and have it allocated.
So, what you want is a pointer to an array of pointers (each to an array)? That is different from an 2D array, although often treated as such for simplicity.
Just like you added an additional layer of indirection when you allocated that single array, you can add a layer of indirection to allocate an array of pointers, and the pointed to arrays of integers.
So, you could write a function like void alloc(int ***num). Yes, this is possible, but not very good design.
But using a pointer for the indirection makes the syntax more complex, and has the risk of a user passing a null pointer to the function. Instead, a better alternative would be to use a reference: void alloc(int **&num).
Since the function allocates something and "returns a pointer", it would make more sense to actually return the pointer: int** alloc(). Much prettier, isn't it? Less indirection is better.
Finally, there is the problem that a user of the function has to know how to delete the allocated memory. Was it allocated with new or new[]? Maybe even malloc? Or does the function perhaps return a pointer to a static object, that must not be deleted? The caller of the function cannot know that unless it is documented separately.
Also, what if one of the allocation fails? There will be an exception, and the earlier allocations will leak.
The C++ way to solve the above 2 problems is to use a RAII container to manage the memory. Since you apparently want to have an array with pointers to arrays, there is a ready made solution in the standard library for you: return a std::vector<std::vector<int>>. If you instead want a proper non-jagged 2D array i.e. a matrix, then you may want to write a custom RAII container for that, possibly using a flat std::vector<int> for the implementation. Note that a third party may already have implemented such container.
Your code looks like C to me. In C++ I would (maybe) use custom types and not do any manual dynamic allocation. For example
typedef std::vector<int> Row;
typedef std::vector<Row> Matrix;
Matrix initMatrix(int nRows,int nCols) {
return Matrix(nRows,Row(nCols));
}
well in that case you dont even need a function but you can just call the constructor (and let array allocate the memory for you).

How do I transform array of class objects into vector array?

So now i have an array of class objects like this:
ClassA* object1[10];
object1[0] = new ClassA();
object1[1] = new ClassA();
Now i would like to use schablone:
vector <ClassA> ver(10);
I am not sure if this is correct. Template, but how do i insert new objects into this vector array in main function?
how do i insert new objects into this vector array in main function
ver already contains 10 default initialized objects. So you can go and start using the objects. Bonus is you don't need to delete it.
Possible usage ver[3].classAFunc();
If number of objects is fixed and known at compile time, std::array may be better choice over std::vector in most cases.
You can add them either by pushing back or emplacing back. Example:
std::vector<ClassA*> objects;
objects.push_back(new ClassA());
object1.push_back(new ClassA());
Or you can use an initializer list:
std::vector<ClassA*> objects{{new ClassA(), new ClassA()}};
You still need to remember to delete the objects.
Better would be to have a vector of shared_ptrs.
Why are you using raw pointers and raw dynamic arrays in the first place?
The C++ way to create the dynamic array in your first line would be the following:
std::vector<ClassA*> object1(10);
This creates a vector with 10 null pointers in it.
The next two lines could be the same, but you'd still have the issue of manually managing the object lifetimes and memory of the ClassA objects. Let's fix that by using smart pointers:
std::vector<std::unique_ptr<ClassA>> object1(10);
object1[0] = std::make_unique<ClassA>();
object1[1] = std::make_unique<ClassA>();
Depending on the circumstances you probably won't need a vector with exactly 10 elements and the last 8 being null pointers. If you want the vector to contain only the elements that are actually set, then do not assign an initial size to the vector and just push in the objects you acutally have:
std::vector<std::unique_ptr<ClassA>> object1; //empty vector
object1.push_back(std::make_unique<ClassA>()); //now has 1 element
object1.push_back(std::make_unique<ClassA>()); //now has 2 elements
And as a last improvement, unless you really need there to be pointers in the vector (e.g. because you have polymorphic elements), just use a vector of objects, not of pointers:
std::vector<ClassA> object1; //empty vector
object1.push_back(ClassA{}); //now has 1 element
object1.push_back(ClassA{}); //now has 2 elements

C++ array size in main

I am learning c++ and I have these doubts:
I want to initialize the array at run time but the size of array also needs to be read at run time.
int size;
int main(){
//read size
size = <value read above>;
CIwUIButton* buttons[size];
}
This does not compile and says size must be constant.I come from Java background and I could achieve the same functionality by following same logic.How to do it in c++.
I am using vector as an equivalent to Java ArrayList.I want a reference to vector outside main but want to initialize it inside main.Again max_size will be read from user input and all elements should be initialized to 0;
vector<int> elements;
int main(){
//read size
int size = <value read above>;
//how to do following in c++
elements = new vector<int>(size);
}
Right, so C++ is not Java, and Java is not C++. They are both separate languages.
If you have an unknown number of "things", you need to use either a vector or dynamically allocate using new. So if you want size number of CIwUIButton pointers:
CIwUIButton** buttons = new CIwUIButton*[size];
(Make sure you use delete [] buttons later - after deleting each button).
If you want size number of buttons:
CIwUIButton* buttons = new CIwUIButton[size];
Again, use same as above to delete the buttons, but you won't need to delete the buttons themselves)
You could also use vector for CIwUIButton.
If you want size number of integers in a global vector called elements then:
elements.resize(size);
(There is near no situation where you need to call new for a vector object - that's probably wrong, unless you know exactly why you are doing it)
For the first part;
you need to allocate array dynamically as follows:
CIwUIButton** buttons = new CIwUIButton*[size];
(Do not forget to delete that object and its elements using destructor and delete [].)
If you want to use non-default constructor you need to initialize each object in a loop:
for(int i=0;i<size;i++) {
buttons[i] = new CIwUIButton(x,y);
}
Second question;
std::vector<int> elements;
You do not need to give a size, however you can define a size like this:
elements.resize(size);
In C++, we follow this idiom known as RAII.
Resource Acquisition Is Initialization.
When you declare an instance of an object A inside a scope:
{
A instance;
}
This object will be destroyed when we leave the scope.
In the case of your global std::vector<int>, it will be created and initialized when the program begins execution and it will be deallocated when the program terminates.
There is no need for new and delete in such a case.
std::vector has a resize method that allows you to resize the internal array so you can access and modify the elements via operator[]. You can also push_back or emplace_back without having to resize.
You can use vector just like this:
vector<int> elements;
int main(){
//read size
int size = <value read above>;
//how to do following in c++
elements.resize(size, 0);
}
In Java, all new objects need to be created with the "new" keyword, but in C++ that is not always the case. elements will be a constructed object by virtue of its declaration, ready to use in main. You can set its size by calling the resize method. Alternatively you can declare elements in main (and not outside as a global variable) and pass the size of the vector as a constructor arguement.
These are basic topics and I suggest you read tutorials on C++ before continuing.
You can make buttons a
vector<CIwUIButton *>
and set its size in the class constructor. But you will also need to manage how the button elements are created.
Variable length arrays are introduced in C99, but C++ doesn't support it.
To use vector:
vector<int> elements;
int main(){
//read size
int size = <value read above>;
elements.resize(size);
}
std::vector doesn't have a fixed size there is no reason to initialize to a specific size, it will just grow on demand. You can do elements.reserve(size) which allocates space for the size elements (ints in your example).
t and all elements should be initialized to 0;
Your elements vector is not a pointer its an Object that is constructed by calling the constructor there is no dynamic memory management needed as it is not even allocated on the heap.
new and delete (don't forget deletes , or better use smart pointers) are used with pointers only.
example :
int main()
{
std::vector<int> elements; // not a pointer constructor called because of this statement
std::vector<int> *elements_ptr = new std::vector<int>(); // this is a pointer pointers have asterisks as part of their declaration and these are initialized via new they simply contain a memory location
// do stuff here
delete elements_ptr; // frees allocated memory and calls the destructor for the object
return 0;
} // elements destructor is called when it goes out of scope
If you are this new to the language I highly recommend reading a book about C++.These are things that are best described by such material.
I would recommend deitel's how to program C++ or the C++ programming language by Bjarne Stroustrup
For using new you'll just need a vector<int>* pointer. The preferred solution for C++ is to use the vector<T>::resize() operation:
vector<int> elements;
int main(){
//read size
int size = <value read above>;
//how to do following in c++
elements.resize(size,0);
}
First I wouldn't use global variables, it is some kind of evil.
If you do not know, how many objects/variables you will need, you have two options, either use some container, or dynamically allocate memory.
I would suggest to use container, but first about dynamical allocation. In C malloc and free in C++ new and delete. C type allocation gives you piece of memory and C++ type does the same and calls constructor and destructor, I suggest to use C++ allocators.
How to use it:
Object *ptr; //pointer to some object
ptr = new Object; //creating one object
delete ptr; //deleting that object, destructor called and memory deallocated
ptr = new Object[n]; //created n objects, to reach any of them just use array index
delete [] ptr; //deleted array. n destructors called all memory freed
If you create array of object, do not use delete without [].
So it is about your own allocators. In your case using vector is probably the best option. But I'll say it once again, global variables is bad idea. I would recommend to pass a reference to it when you call function.
There are a few ways of function prototypes in C++
/*1*/foo(Object obj); //value of given object will be copied it's slow but sometimes we need that
/*2*/foo(Object *obj); //passing pointer more C type. Fast but unsafe.
/*3*/foo(Object &obj); //C++ passing reference. It is the same as passing pointer but it is C++ type declaration, it is safer because you won't pass NULL and you won't go out of memory
/*4*/foo(const Object *obj);
/*5*/foo(const Object &obj); //Same as before one is C type, another C++ type (unsafe and safer). Keyword `const` means what value won't be changed.
Calls to these functions look like this:
Object obj;
/*1*/foo(obj);
/*2*/foo(&obj);
/*3*/foo(obj);
/*4*/foo(&obj);
/*5*/foo(obj);
So going back to your question.
If you really want to use global variable, so you will need to resize your container. In your case it is elements.resize(size); But I wouldn't use global data so my option would be:
typedef std::vector<CIwUIButton> ButtonVector; //in big projects typedef makes us to type less :)
size_t size = <value read above>;
ButtonVector buttons(size); //You will need default constructor to initialize all buttons
I've seen a pointer in your code, not sure, what you wanted to do with that but I think it is not necessary.
BTW you should read about STL containers because C++ and JAVA differs. Especially read about vector and deque. In your case vector is probably better then deque but you mentioned ArrayList and it is much more deque then vector.
EDIT If you are really want to start programming with C++ you should also look at boost in your case scoped_array and shared_ptr may be useful.
You have to allocate memory dynamically, use malloc and assign sizeof(yourClass) * size to the pointer you have created

Vector of pointers: some clarification needed

I have read a lot about vector of pointers on this forum but have trouble grasping the idea of deleting the pointers stored in the vector. Following is my query:
Suppose I dynamically create an array of objects
CPoint* dynamic_array;
dynamic_array = new CPoint[30714];
I now have to use these values in object of another class through vector of pointers
vector<CPoint*> vector_of_pointers;
I will then divide the elements of dynamic_array into objects of another class using the following
Class B{
vector<CPoint*> vector_of_pointers;
public:
void function(CPoint* a){
if (some condition){
vector_of_pointers.push_back(a);
}
};
Where a will always be a pointer to object from dynamic_array
I then plan to delete the originally created dynamic_array, after the need for its objects is over.
delete[] dynamic_array;
Is deleting each pointer in the vector necessary even after doing this? And if it is necessary can I do it in the destructor for Class B?
Sorry if this is a simple or silly question but I am newbie in c++ and using a container is necessary for my application.
To answer your original question: No, you don't need to delete individual CPoint objects (in fact you can't).
But I do believe that you'd be better off using vector<CPoint> to store the actual point, rather than a pointer to it.
The pointers that you store in your vector<CPoint*> point to objects that you already deleted with your delete[] dynamic_array instruction, so you don't have to, and also should not, add delete instructions on the individual pointers stored in your vector.
Is deleting each pointer in the vector necessary even after doing this? And if it is necessary can I do it in the destructor for Class B?
The answer is no and in fact you can't.
Whether or not it is better to just use std::vector I think it depends on your needs but I can confirm that using new[] is a lot faster than creating each object separatelly. Some times:
class CPoint {
public:
float x; float y;
}
const int N = 1e6;
for(int i = 0; i < N; ++i)
{
new CPoint();
}
// 122 ms
CPoint* points = new CPoint[N];
// 0.00793176 ms
std::vector<CPoint*> vectorPoints(N); // same as above
// 4.48263 ms
Using std::vector<CPoint*>(N) is also fast but not faster as new[]
deleting CPoint objects pointed by pointers in the vector is not necessary and is impossible but the pointers in the vector must be removed from the vector.
you must clear the vector because it holds at least 4*number_of_elements(8*number_of_elements in x64 systems) of useless pointers.

Define array, then change its size

I come from a java background and there's something I could do in Java that I need to do in C++, but I'm not sure how to do it.
I need to declare an array, but at the moment I don't know the size. Once I know the size, then I set the size of the array. I java I would just do something like:
int [] array;
then
array = new int[someSize];
How do I do this in C++?
you want to use std::vector in most cases.
std::vector<int> array;
array.resize(someSize);
But if you insist on using new, then you have do to a bit more work than you do in Java.
int *array;
array = new int[someSize];
// then, later when you're done with array
delete [] array;
No c++ runtimes come with garbage collection by default, so the delete[] is required to avoid leaking memory. You can get the best of both worlds using a smart pointer type, but really, just use std::vector.
In C++ you can do:
int *array; // declare a pointer of type int.
array = new int[someSize]; // dynamically allocate memory using new
and once you are done using the memory..de-allocate it using delete as:
delete[]array;
Best way would be for you to use a std::vector. It does all you want and is easy to use and learn. Also, since this is C++, you should use a vector instead of an array. Here is an excellent reason as to why you should use a container class (a vector) instead of an array.
Vectors are dynamic in size and grow as you need them - just what you want.
The exact answer:
char * array = new char[64]; // 64-byte array
// New array
delete[] array;
array = new char[64];
std::vector is a much better choice in most cases, however. It does what you need without the manual delete and new commands.
As others have mentioned, std::vector is generally the way to go. The reason is that vector is very well understood, it's standardized across compilers and platforms, and above all it shields the programmer from the difficulties of manually managing memory. Moreover, vector elements are required to be allocated sequentially (i.e., vector elements A, B, C will appear in continuous memory in the same order as they were pushed into the vector). This should make the vector as cache-friendly as a regular dynamically allocated array.
While the same end result could definitely be accomplished by declaring a pointer to int and manually managing the memory, that would mean extra work:
Every time you need more memory, you must manually allocate it
You must be very careful to delete any previously allocated memory before assigning a new value to the pointer, lest you'll be stuck with huge memory leaks
Unlike std::vector, this approach is not RAII-friendly. Consider the following example:
void function()
{
int* array = new int[32];
char* somethingElse = new char[10];
// Do something useful.... No returns here, just one code path.
delete[] array;
delete[] somethingElse;
}
It looks safe and sound. But it isn't. What if, upon attempting to allocate 10 bytes for "somethingElse", the system runs out of memory? An exception of type std::bad_alloc will be thrown, which will start unwinding the stack looking for an exception handler, skipping the delete statements at the end of the function. You have a memory leak. That is but one of many reasons to avoid manually managing memory in C++. To remedy this (if you really, really want to), the Boost library provides a bunch of nice RAII wrappers, such as scoped_array and scoped_ptr.
use std::array when size is known at compile time otherwise use std::vector
#include <array>
constexpr int someSize = 10;
std::array<int, someSize> array;
or
#include <vector>
std::vector<int> array; //size = 0
array.resize(someSize); //size = someSize
Declare a pointer:
int * array;