C++ array size in main - c++

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

Related

Class size instantiated in a sub-function, i.e. is this a good time to use new?

I want to create a vector of data, but I want to both set it's size and fill its elements in a sub-function. Is this an appropriate time to use the new operator? Is there a better way to do it? It seems like an appropriate time, but I'm hesitant because of Why should C++ programmers minimize use of 'new'?
int main()
{
vector<double> *array1;
vector<double> *array2;
OtherArgs otherArgs;
FillArrays(array1,array2,otherArgs);
//Do other stuff
delete array1;
delete array2;
}
void FillArrays(vector<double> *&array1, vector<double> *&array2, OtherArgs &otherArgs)
{
int size=GetSize(otherArgs);
array1 = new vector<double>(size);
array2 = new vector<double>(size);
//Other code to fill the arrays
}
Thank you
Here are a couple of reasons why the original sample is troublesome
The code leaks memory in the face of an exception because the delete calls aren't protected
If FillArrays is passed a non-NULL vectory<double> value it will leak memory because it didn't delete the previous value. It couldn't reliably call delete even if it wanted to because the value may have been stack allocated.
The easiest way to do this is to just declare the values on the stack and pass them by reference that way.
int main()
{
vector<double> array1;
vector<double> array2;
OtherArgs otherArgs;
FillArrays(array1,array2,otherArgs);
//Do other stuff
}
void FillArrays(vector<double> &array1, vector<double> &array2, OtherArgs &otherArgs)
{
int size=GetSize(otherArgs);
//Other code to fill the arrays
}
The vector<T> will initialize themselves to an empty list when declared in this manner. The FillArrays method can then populate them as necessary.
No, this is a specifically bad use of new.
If you must use new and delete1, use them as bookends. The delete expression should be in a logically consistent context with the new expression.
So, if you new in a c-tor, you should delete in the d-tor. If you new in an allocation function, you should delete in a deallocation function. The two calls should be arranged in an way that makes it obvious that one starts an operation and the other finishes it.
This implies that the call to new and delete should exist in the same layer in a functional or object hierarchy. Specifically, new and delete should be seen as implementation details, and not as part of the API contract.2
In your case, the new and delete are in entirely distinct contexts. new is inside the implementation, while delete is called for in the client. This will lead to programming errors.
Beyond that, the non-new version of your code (creating empty vectors in main, and passing them by reference) is simpler, easier to read, and more exception-friendly than the new version.
No, this is not a good example of when to use new. It is, however, an excellent example of when not to.
1 You hardly ever need to use new and delete. If you need dynamic allocation, just let containers keep copies of your objects.
2 std::shared_ptr, et al, violate this rule -- the new and delete are specifically part of the contract. This is probably OK, since pointer manipulation is their reason for existence. But SO has seen its share of bugs about storing a non-new pointer in shared_ptr.

Can a vector allocated on the "stack" be passed from function to function?

I know that variables allocated on that stack of a function become inaccessible when the function finishes execution. However, vector types allocate their elements on the heap no matter how they are allocated. So for instance,
vector<int> A;
will allocate space for its elements on the heap instead of the stack.
My question is, assume I have the following code:
int main(int argc, char *argv[]) {
// initialize a vector
vector<int> A = initVector(100000);
// do something with the vector...
return 0;
}
// initialize the vector
vector<int> initVector(int size) {
vector<int> A (size); // initialize the vector "on the stack"
// fill the vector with a sequence of numbers...
int counter = 0;
for (vector<int>::iterator i = A.begin(); i != A.end(); i++) {
(*i) = counter++;
}
return A;
}
Will I have memory access problems when using the vector A in the main function? I tried this several times and they all worked normally, but I'm scared that this might just be luck.
The way I see it is, the vector A allocates its elements on the heap, but it has some "overhead" parameters (maybe the size of the vector) allocated on the stack itself. Therefore, using the vector in the main function might result in a memory access problem if these parameters are overwritten by another allocation. Any ideas?
When you do "return A;" you return by value, so you get a copy of the vector -- C++ creates a new instance and calls copy constructor or operator= on it. So in this case it doesn't matter where the memory was allocated as you have to copy it anyway and destroy the old copy (some possible optimizations notwithstanding).
The data in the vector (and all other STL containers) is moved around by value as well, so you store the copy of your integers, not pointers to them. That means your objects can be copied around several times in any container operation and they must implement a copy constructor and/or assignment operator correctly. C++ generates those for you by default (just calling copy ctor on all your member variables), but they don't always do the right thing.
If you want to store pointers in an STL container consider using shared pointer wrappers (std::shared_ptr or boost::shared_ptr). They will ensure the memory is handled correctly.
Yes, it will work normally because the memory for the elements are allocated and that is what will be used to build the vector<int> A = variable. However, performance wise, it is not the best idea.
I would suggest changing your function to be the following though
void initVector(vector<int>& a, int size)
For additional references on usage, please see Returning a STL vector from a function… and [C++] Returning Vector from Function.
For an additional reference on performance (using C++11), please see Proper way (move semantics) to return a std::vector from function calling in C++0x
C++ vector actually has two pieces of memory that are linked with a single pointer. The first one is in stack, and the 2nd one in heap. So you have features of both stack and heap in a single object.
std::vector<int> vec;
vec.push_back(10);
vec.push_back(20);
vec.push_back(30);
std::cout << sizeof(vec) << std::endl;
Once you run that code, you'll notice that the stack area does not contain the elements, but it still exists. So when you pass the vector from function to another, you'll need to manipulate the stack areas, and the vector will get copied like any other stack-based object.

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;

Cleaning up a dynamic array of Objects in C++

I'm a bit confused about handling an array of objects in C++, as I can't seem to find information about how they are passed around (reference or value) and how they are stored in an array.
I would expect an array of objects to be an array of pointers to that object type, but I haven't found this written anywhere. Would they be pointers, or would the objects themselves be laid out in memory in an array?
In the example below, a custom class myClass holds a string (would this make it of variable size, or does the string object hold a pointer to a string and therefore take up a consistent amount of space. I try to create a dynamic array of myClass objects within a myContainer. In the myContainer.addObject() method I attempt to make a bigger array, copy all the objects into it along with a new object, then delete the old one. I'm not at all confident that I'm cleaning up my memory properly with my destructors - what improvements could I make in this area?
class myClass
{
private:
string myName;
unsigned short myAmount;
public:
myClass(string name, unsigned short amount)
{
myName = name;
myAmount = amount;
}
//Do I need a destructor here? I don't think so because I don't do any
// dynamic memory allocation within this class
};
class myContainer
{
int numObjects;
myClass * myObjects;
public:
myContainer()
{
numObjects = 0;
}
~myContainer()
{
//Is this sufficient?
//Or do I need to iterate through myObjects and delete each
// individually?
delete [] myObjects;
}
void addObject(string name, unsigned short amount)
{
myClass newObject = new myClass(name, amount);
myClass * tempObjects;
tempObjects = new myClass[numObjects+1];
for (int i=0; i<numObjects; i++)
tempObjects[i] = myObjects[i]);
tempObjects[numObjects] = newObject;
numObjects++;
delete newObject;
//Will this delete all my objects? I think it won't.
//I'm just trying to delete the old array, and have the new array hold
// all the objects plus the new object.
delete [] myObjects;
myObjects = tempObjects;
}
};
An array in C++ is an array of objects laid out in memory.
So for example in:
struct pair {
int x; int y;
};
...
pair array[10];
Each item in the array is going to be with a size of two ints.
If you want an array of pointers you can simply declare one:
pair* array_of_pointers[10];
The string objects have pointers to the variable size part of the string. So they're safe.
In fact they're the important lesson here. Same way you use the string class to avoid excessive memory handling you can use the vector class to avoid all the troubles of handling a dynamic array.
For the case you're doing this as an exercise. Here are a few problems:
newObject needs to be allocated locally, without new. This will make the code correct (as newObject is not a pointer and new returns a pointer) and will also save you the trouble of explicitly handling memory. (On a more advanced note, this makes the code exception safe in one more location)
myObject is never initialized. And you don't use initialization lists in the constructor. The constructor should look like this:
myContainer() : numObjects(0), myObjects(NULL)
{
}
The destructors in the code are exactly as they should be.
No, a dynamic array is not an array of pointers to that type - its a pointer to the first element. The elements are laid out consecutively in memory and are destroyed when the array is delete[]ed.
Thus your deallocation looks fine - you create dynamic arrays of myClass objects so you don't have to delete them individually. You would only have to do this if you had an array of pointers to (dynamically allocated) objects.
There are two definitive errors though:
tempObjects[numObjects] = newObject; // assign a myClass pointer to a myClass instance?
This should be e.g.:
tempObjects[numObjects] = myClass(name, amount);
Also, myObjects is never initialized, which means it contains garbage and dereferencing/using it leads to undefined behaviour.
Finally, unless you are doing this for learning purposes, simply use containers like std::vector that do all the work for you already.
I would expect an array of objects to be an array of pointers to that object type, but I haven't found this written anywhere. Would they be pointers, or would the objects themselves be laid out in memory in an array?
The array will consist of the objects themselves. If you want to have an array of pointer you will have to declare that:
myClass ** tempObjects;
tempObjects = new myClass*[numObjects+1];
I assume you are used to C# or Java? In those languages objects can only be allocated on heap and are always accessed by referenced. It is possible in C++, but in C++ you can also put objects directly on the stack, or directly construct an array of the objects themselves.
In the example below, a custom class myClass holds a string (would this make it of variable size, or does the string object hold a pointer to a string and therefore take up a consistent amount of space?
Number two: The string object itself is constant in size, but has a pointer to a dynamically sized buffer allocated from the heap.
I think the deallocation looks fine. The code could be written more efficient in various ways, but it looks correct.
Try to test it, to see what happens (yes, that may be compiler-specific, but still)...
You could try to add a custom destructor to myClass (even though you don't need one), that increments a "global" counter when called, Then print the counter after deleting the array.
I would expect the destructor of each object to be called. Note that quite often objects are stored "by-pointers" to allow for inherited objects to be put into the array (avoiding "slicing").

Array of Pointers

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.