Dynamic object creation - c++

I am new to c++ programming and I have a basic issue, I want to create N objects, N is is actually a user input.
I am specific about having object names, say beam1, beam2,...,beamX.
2 quick things
Is it possible in C++ to create dynamic object as this?
if it is how do we do tht? I am pasting code for your refrence..
#include "iostream"
# include <conio.h>
using namespace std;
// Static member variable is defined outside the class..
class beam {
public:
int length;
};
int main ()
{
int i=0, no_of_spans, j;
cout<< "Design Of a Continous Beam \n1) No Of Spans : ";
cin >> no_of_spans;
for (i =0; i < no_of_spans; i++) {
j = i;
beam;
cout << "Length of Beam" << j+1 << " is : ";
cin >> beami.length;
}
cout << "\nPress any key to continue..\n";
getch ();
}
This is obviously a code with errors, its put up as an example to get the idea.

As has already been stated by others (Luchian, John, Component and Ed) you can use a std::vector and it will dynamically grow as necessary to store the number of beam objects required.
If you wish to refer to these objects later by name you could store them in a std::map, with the key of the map being the object name (e.g. beam1, beam2, beam3, ..., beamX):
std::map<std::string, beam> beams;
for (int i = 0; i < no_of_spans; i++)
{
j = i;
beam beam;
std::string beam_name("beam" + boost::lexical_cast<std::string>(i + 1));
cout << "Length of " << beam_name << " is : ";
cin >> beam.length;
beams.insert(std::make_pair(beam_name, beam));
}
--
boost::lexical_cast<> is a mechanism for converting (in this case) an int to a std::string. There other ways to achieve this (using std::ostringstream for example).

You can use a std::vector to store the objects.
You use push_back to add elements to the vector.
Something along the lines of:
std::vector<beams> beamCollection;
for (i =0; i < no_of_spans; i++) {
j = i;
beam beami;
cout << "Length of Beam" << j+1 << " is : ";
cin >> beami.length;
beamCollection.push_back(beami);
}

Yes, of course it's possible. There are several ways.
One way, the way I'd prefer if possible/practical, is to use std::vector and push_back, transform or generate_n how ever many objects you needed.
Another way is to use new to allocate an array of the object you want. This is less preferred to using a vector however, because by using new you take on the responsibility of managing the memory -- there needs to be a delete that corresponds to every new. This can be mitigated by using a smart pointer such as std::unique_ptr, but it's often best to just avoid the cactus altogether.

Yes, it is possible. Your best bet is to use an appropriate STL collection and dynamically grow it at runtime by adding / removing objects.

Short answer no - the compiler needs to know the names of variables at compile time.
You need to use an array (or vector).

Related

Problem with declaring a dynamic array of pointers to strings

While performing a practice assignment online I came across a problem which I am not able to solve.
The user has to a number(number of sentences he will be entering) and then proceed to enter the sentences one by one, which are to be stored as strings(by the way, declaring a dynamic array of pointers is mandatory). However, since the number of sentences is not a priori deducible, I know that the size of the array of pointers actually is the number of sentences but I can't figure out how to declare a dynamic array of pointers to strings.
Using something I had already known beforehand, I figured out how to do the same but with arrays of characters, not arrays of strings. The line that declared a dynamic array of pointers to dynamic arrays of chars looked like this:
char **ptr=new char*[n] {};
So with my understanding, this creates a pointer ptr which points to a dynamic array of pointers, the elements of which each point to one array of characters. I want to do something similar now, where the result should be that ptr is a pointer to a dynamic array of pointers, the elements of which each point to a string.
Can anyone help out? I'd be thankful!
I think what you are looking for is something like
std::size_t num;
std::cout << "enter the number of sentences\n";
std::cin >> num;
std::string *sentences = new std::string[num];
for(std::size_t i=0; i!=num; ++i) {
std::cout << "enter the " << (i+1) << "th sentence\n";
std::cin >> sentences[i];
}
/*
... (do something with the sentences, accessing them as sentences[i])
*/
delete[] sentences; // free the memory
Note that this style of coding is highly discouraged. The problem is the need to manage the allocated memory: avoid memory leaks and dangling pointers (including exception safety). The correct approach is to use a container or smart pointer. For example:
std::size_t num;
std::cout << "enter the number of sentences\n";
std::cin >> num;
std::vector<std::string> sentences{num};
for(std::size_t i=0; i!=num; ++i) {
std::cout << "enter the " << (i+1) << "th sentence\n";
std::cin >> sentences[i];
}
/*
... (do something with the sentences, accessing them as sentences[i])
*/
or
std::size_t num;
std::cout << "enter the number of sentences\n";
std::cin >> num;
std::unique_ptr<std::string[]> sentences{new std::string[num]};
for(std::size_t i=0; i!=num; ++i) {
std::cout << "enter the " << (i+1) << "th sentence\n";
std::cin >> sentences[i];
}
/*
... (do something with the sentences, accessing them as sentences[i])
*/
when in both cases you don't have to worry about calling delete: the allocated memory will be automatically deleted (even if an exception occurs).
You can avoid pointers completely and use
std::vector<std::string> input;
A std::array needs to know the size at compile time, and you learn this at runtime. The vector works like an array but can have items push_backed at runtime.
You could declare pointer to some strings, using n once you know it:
std::string * pInputs = new std::string[n];
but it's easier to use the vector.
Each pInput will be a string, as with the std::vector version.

C++ Displaying a Vector when using a pointer

#include <iostream>
#include <vector>
int main()
{
unsigned int numVec;
unsigned int input;
std::cout << "Enter Number of Vectors: ";
std::cin >> numVec;
std::vector<int>* Vec;
for (unsigned int i = 0; i < numVec; i++)
{
std::cout << "Enter Vector Value " << i << ": ";
std::cin >> input;
Vec->push_back(input);
}
std::cout << std::endl;
for (unsigned int i = 0; i < Vec->size(); i++)
{
std::cout << "Value at Index (" << i << ") " << Vec->at(i) << std::endl;
}
std::cout << std::endl;
return 0;
}
I am trying to learn how Vectors work as it is a topic that i have withheld learning for a very long time for no apparently reason.
My above code will compile and run however once i put in a number to store in the Vector it will crash.
The program did work before when i was just using a vector without the pointer but just for learning reasons i wanted to try it with a pointer, I am just wondering what am i doing wrong with this code and if someone could possibly flame me for doing something or give me some good advice on what i am doing wrong in this situation so i can learn for future reference.
Replace
std::vector<int>* Vec;
with
std::vector<int> vec;
and replace the pointer to member operator -> with the member selection operator ..
Only on rare occasions do you need to use dynamic storage for a std::vector instance, as that class does an excellent job of managing the memory for you. Currently you are not allocating any memory for your vector, and the behaviour of your code is undefined.
If you must use a pointer then write
std::vector<int>* vec = new std::vector();
and don't forget to call delete vec; when you're done. Consider using std::unique_ptr &c. so the delete is taken care of automatically.
My above code will compile and run however once i put in a number to store in the Vector it will crash.
What vector?
You never created a vector.
You only created a pointer, one which (a) is uninitialised, and (b) does not point to anything, let alone a (c) vector.

Wrong value in array which contains instances of a class (C++)

I use an array to create instances of a class.
I declared them in the Header file:
Figure *soldier;
Fight *weapon;
In the cpp I use the following code to create it:
std::cout << "How many soldier? ";
std::cin >> i_soldier;
std::cout << "How many weapon? ";
std::cin >> i_weapon;
soldier= new Figure[i_soldier];
weapon = new Fight[i_weapon];
The class Figure has this constructor:
Figure::Figure()
{
position = 0;
}
When I'm running the code it compiles fine, but when I look the position at the begin, the last array entry has a wrong value; I guess it points at a value from a memory address. All the other entries have the value 0.
This is how I say which instance I want to go.
for(int i = 0; i <= i_soldier; i++)
{
soldier[i].position();
}
Does anybody know where the error can come from?
Arrays are 0-indexed, the last position of the array is i_soldier-1, change your condition to a strict <.

When to use new for an object and when to use pointers?

For example, I have a vector which is declared this way:
vector<Shapes> *ShapeVector;
If I want to have a shape object, and to be able to access different shapes that're of different sizes, would declaring 'new' or not be needed? What about pointers then?
To me, pointers point to different addresses to access. So, would I need pointers too?
So far, I did the following code to create my object, and to store arrays in it. After that, I would plan to store the object into the vector itself.
int tempx[100],tempy[100];
for (int i = 0; i < 4;i ++)
{
cout << "Enter x-coordinate of pt " << i << ":" << endl;
cin >> tempx[i];
cout << "Enter y-coordinate of pt " << i << ":" << endl;
cin >> tempy[i];
Square mysquare = new Square(tempx,tempy);
Not sure if it's correct though, unsure on when to use 'new' and when to use pointers.
You can use simply std::vector<Shapes> my_vector, without pointers. The vector object will be allocated on the stack, its content on the heap. You will have the advantage that the Shape objects will be placed contiguously in memory.

C++ vector accessing elements

How can I access elements from myVector like i would do with arrays ( for(i = 0; i < n; i++) cout << v[i] << " "; )
My code:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Month
{
public:
char *name;
int nr_days;
Month(char* c, int nr) : name(c), nr_days(nr){};
~Month() { /* free(name); */}
};
int main()
{
Month January("January", 31);
Month February("February", 28);
Month March("March", 31);
Month April("April", 30);
Month May("May", 31);
Month June("June", 30);
Month July("July", 31);
Month August("August", 31);
Month September("September", 30);
Month Octomber("Octomber", 31);
Month November("November", 30);
Month December("December", 31);
vector<Month> *myVect = new vector<Month>;
myVect->push_back(January);
myVect->push_back(February);
myVect->push_back(March);
myVect->push_back(April);
myVect->push_back(May);
myVect->push_back(June);
myVect->push_back(July);
myVect->push_back(August);
myVect->push_back(September);
myVect->push_back(Octomber);
myVect->push_back(November);
myVect->push_back(December);
for(vector<Month>::const_iterator i = myVect->begin(); i != myVect->end(); i++)
{
/*
Month myMonth = i;
cout << myMonth.name << " " << myMonth.nr_days << endl;
*/
}
free(myVect);
return 0;
}
I would want to be something like a foreach algorithm: foreach(Month in myVect) cout << ...
And another question: why it gives me a run-time error at the destructor if I uncomment my line?
Ok, there are a lot of problems here.
You declare myVect as a pointer to a vector. This is unnecessary. One of the major benefits of using a vector is so that you don't have to worry about memory management as the vector does it for you. You stack allocate the vector, but internally it heap allocates the memory used to store the items it contains.
You never initialize the pointer. You are invoking undefined behavior as that pointer is not valid. To initialize a pointer you use new. All you have is an invalid stack allocated pointer that does not point to a vector on the heap. EDIT: I just realized that the new was edited out, so you can disregard this one. Still, it shouldn't be a pointer at all.
You are using free to deallocate a C++ class (that you never allocated to begin with...). Don't. This isn't C, you use new and delete to manage memory (when necessary!) in C++. free does not call destructors, it simply frees up a chunk of memory. delete on the other hand does as it knows how to deal with complex C++ types. Never mix new/delete with malloc/free.
myVect->begin() returns a const_iterator, not a T (i.e., in this case, not a Month object). Dereferencing the iterator via the * operator will yield the current iteration object, so:
Month myMonth = *i // <--- IMPORTANT!
As an aside, if you are going to be looping over the vector often you may want to typedef the iterator to reduce verbosity, i.e.,
typedef vector<Month>::const_iterator cmonth_iter;
Now you can write
for(cmonth_iter i = myVect.Begin(); i != myVect.end(); ++i )
{
Month m = *i;
// do stuff with m
}
You can access elements using iterator using the * operator:
for(vector<Month>::const_iterator i = myVect->begin(); i != myVect->end(); i++)
{
Month myMonth = *i;
cout << myMonth.name << " " << myMonth.nr_days << endl;
}
Also, you never allocate a vector in your code. You shouldn't use free() on a pointer you haven't received from malloc() earlier. It is undefined behavior to do otherwise and a run-time error is likely to occur at the point you call free().
Try this:
vector<Month> *myVect = new vector<Month>;
...
delete myVect;
If you remove the unitialized pointer bug by changing:
vector<Month> *myVect;
to:
vector<Month> myVect;
Then this will work. (Once you define ostream << Month)
for(i = 0; i < myVect.size(); i++)
cout << v[i] << " ";
You have a pointer myVect, but never assign a value to it before using (turn compiler warnings on). you should do something like myVect = new vector<Month>(). (or do not make it pointer and change -> into .). The rest of your "foreach" implementation looks fine. And you can use [] to access elements as well.
You free constant strings, you did not allocate them, so you need not to free them either.
You're declaring myVect as a pointer but never allocating it, that's going to give you lots of trouble. Just drop the * and you should be fine.
If you insist, you can use an index just like you would with an array:
for(int i = 0; i < myVect.size(); i++)
{
Month myMonth = myVect[i];
cout << myMonth.name << " " << myMonth.nr_days << endl;
}
Although I'd rather use iterators as you have done - just one simple fix:
Month myMonth = *i;
You can use the arrow operator with iterators...
for(vector<Month>::const_iterator i = myVect->begin(); i != myVect->end(); i++)
{
cout << i->name << " " << i->nr_days << endl;
}
note also that it's more idiomatic with iterators using ++i instead of i++ (the reason is that i++ will need to create a copy of the iterator that will be thrown away).
Note also that your code is UB (undefined behavior) because you are using a pointer to a vector, but you are not allocating it. By the way the use of a pointer in this case is nonsense, the code would be correct and simpler with:
vector<Month> myVect;
myVect.push_back(January);
myVect.push_back(February);
...
for(vector<Month>::const_iterator i = myVect.begin(); i != myVect->end(); ++i)
...
My suggestion is also to avoid to try learning C++ just by experimenting with a compiler (something that I've the impression you're trying to do).
C++ is powerful but also complex and unfortunately quite illogical and asymmetrical in many parts (due to its evolution history). Add to this that when you make a mistake (e.g. not allocating the vector in your original code) you cannot expect the compiler to help you and even at runtime the program may do ANYTHING, including apparently work as you expected (the worst possible thing). This combo is deadly.
Complexity, asymmetry and lack of runtime checks all make C++ impossible to learn by experimentation... just get a good book and read it. It's much simpler this way.