Can you create objects using variables in C++ - c++

I want to create a number of objects of a class, but this number won't be known until runtime. Intuition tells me that I should use the following loop to create my objects:
for (int count = 0; count < no_of_objects; count ++)
{
ClassName object_name[count]
}
This, however does not work as the compiler doesn't appear to like using variables as object names. Is there a way I can create these objects using a loop, or do I have to use some other method.
Please bear in mind that I have not been using C++ for long and have only recently been introduced to programming, so my knowledge of the language is somewhat limited - so far, the array is the only data structure I have been taught - no vectors, etc.

It's time to learn vectors:
std::vector<ClassName> objects (no_of_objects);
Now use objects[0] through objects[no_of_objects - 1]; note that objects.size() equals no_of_objects. When you're ready, look at vector's methods, etc., but for now, this plus knowing the header to include (<vector>) is enough to use objects as a dynamic array.

In C++ you will have to allocate this dynamically if you do not know the number of objects until runtime. You would need code similar to this:
ClassName* pmyClasses = new ClassName[no_of_objects];
This will allocate an array to hold your class objects, you then need to initialize them.
for (int i=0; i < no_of_objects; i++)
{
pmyClasses[i] = new ClassName();
}
You can then access them via the array indexer:
for (int i=0; i < no_of_objects; i++)
{
pmyClasses[i].SomeFunction();
}
An important thing to note here is that if you use new to allocate memory, then you need to use delete to deallocate it. Since this is an array declaration then you need to use the delete [] operator.
for (int i=0; i < no_of_objects; i++)
{
delete pmyClasses[i];
}
delete [] pmyClasses;
If you are using this inside or a class it would be important to have the delete in the destructor of the class:
class UsingMyClass
{
private:
ClassName* pmyClasses;
public:
UsingMyClass(int no_of_objects)
{
pmyClasses = new ClassName[no_of_objects];
for (int i=0; i < no_of_objects; i++)
{
pmyClasses[i] = new ClassName();
}
}
~UsingMyClass()
{
for (int i=0; i < no_of_objects; i++)
{
delete pmyClasses[i];
}
delete [] pmyClasses;
}
}
By doing this, when the UsingMyClass object goes out of scope (assuming it was not created via a call to new or malloc) then the array of ClassName objects will be cleaned up.

If your class has a default constructor (and you want to default construct the instances), you can use an array new i.e. new ClassName[some_number] - which is of type ClassName*).
If it doesn't have a default constructor, you can fool around with placement new, or use an array of pointers and new each one manually.

TO allocate the memory dynamically you have to use the new keyword
ClassName = new object_name[count];
and make sure to delaocate the memory after by using delete keyword

Related

Adding a pointer in a vector of objects

I am trying to grasp the pointers in C++ but I can't find the answer to these questions.
If I was to have an ArrayList in Java and I wanted to add new Objects to it in a loop I would do something like:
ArrayList<MyObject> list = new ArrayList<MyObject> ();
for (int i = 0; i < otherList.length; i++) {
list.add(i, new MyObject(otherList.get(i)));
}
But let's say I wanted to do the same thing in C++ using vectors. I have found two methods:
vector<MyObject> vector;
for (auto i = otherVector.begin(); i != otherVector.end(); i++) {
// do this
vector[i - otherVector.begin()] = * new MyObject(*i);
// or this
MyObject newObj(*i);
vector[i - otherVector.begin()] = newObj;
}
What is the difference between those 2 methods and if I use the second one, do I need to manually delete the pointers from the list? If I were to use the second method with smart pointers, would they be automatically deleted by the gc when the vector was not used anymore?
The first method creates a memory leak. There's no saving it. Forget you ever heard of operator new.
if I use the second one, do I need to manually delete the pointers from the list?
There are no pointers in the list.
The second would work, and it would clean up after itself when vectorgoes out of scope. But do not do that either.
vector<MyObject> vector;
for (auto i = otherVector.begin(); i != otherVector.end(); i++) {
// do this
vector[i - otherVector.begin()] = * new MyObject(*i); // No, no, no, no.
// or this
MyObject newObj(*i);
vector[i - otherVector.begin()] = newObj; // Please don't.
}
But here's one way it should be done. No loop. (And don't name things "vector".)
std::vector<my_object> vec(other_vector);
If you're really into the brevity thing, do this:
auto vec{other_vector};

Do I need to call delete[] on a member array that is declared with a constant value in class decleration?

here is an example of a code hopefully will demonstrate my confusion
#define MAX_LENGTH 5
class Bar
{
private:
Foo *_myFooArray[MAX_LENGTH];
public:
Bar()
{
for (int i = 0; i < MAX_LENGTH; ++i)
{
_myFooArray[i] = new Foo(i);
}
}
};
Since I am not creating the array with new I don't think I can use delete[] but what if I want to delete the objects that are allocated dynamicly? do I iterate through the array and delete them one at a time? as such;
~Bar()
{
for (int i = 0; i < MAX_LENGTH; ++i)
{
delete _myFooArray[i];
}
}
I will probably hear some of you screaming at me Use Vectors!! I appreciate that. I just want to learn. Just for completeness, If for some reason I have to use the array as mentioned above, are there anything that I need to pay extra attention besides deleting the array correctly?
One of the rules in C++ when not using smart pointers is "every new needs a delete."
You must use the destructor from your question to avoid leaking memory. The array itself is not allocated using new so you do not need to delete it.
No, you do not delete [] the array. The array is part of your instance's data. The elements you allocate specifically are not, so you should delete them.

auto-memory management for pointers of pointers

There are legacy functions that need a dynamic array A**. For example,
A** array = new A*[100];
foo(array, 100);
...
void foo(A** a, int len) {
for(int i=0;i<len; ++i) {
a[i] = A::create(...);
}
}
I was wondering if I could use any "smart" pointers to manage this array.
I could use boost::scoped_array array. Its array.get() returns A**, and so it can work with legacy functions. But I think the destructor of array only free the top-level pointers, but not the second-level.
ptr_vector automatically deletes everything. But it does not have a way to return A**.
Do we have any other solutions?
If the API creates the objects using a call like A::create(...) which returns a pointer, then surely the API has a complementary call to destroy the objects such as A::destroy(ptr). In that case, the following custom deleter should be appropriate:
std::unique_ptr<A*, void(*)(A**)> array_ptr(
new A*[100],
[](A** ptr) {
for(std::size_t i = 0; i < 100; i++)
A::destroy(ptr[i]);
delete[] ptr;
}
);
foo(array_ptr.get(), 100);
EDIT I rewrote my answer, since the first version seemed to have been way off.

Creating c++ vector of pointers

In my C++ code I have a class Object equipped with an id field of type int. Now I want to create a vector of pointers of type Object*. First I tried
vector<Object*> v;
for(int id=0; id<n; id++) {
Object ob = Object(id);
v.push_back(&ob);
}
but this failed because here the same address just repeats itself n times. If I used the new operator I would get what I want but I'd like to avoid dynamic memory allocation. Then I thought that what I need is somehow to declare n different pointers before the for loop. Straightforward way to this is to declare an array so I did this :
vector<Object*> v;
Object ar[n];
for(int i=0; i<n; i++) {
ar[i] = Object(i);
}
for(int i=0; i<n; i++) {
v.push_back(ar+i);
}
Is there still possibility to get a memory leak if I do it this way? Also going through an array declaration is a bit clumsy in my opinion. Are there any other ways to create vector of pointers but avoid manual memory management?
EDIT: Why do I want pointers instead of just plain objects?
Well I modified the original actual situation a bit because I thought in this way I can represent the question in the simplest possible form. Anyway I still think the question can be answered without knowing why I want a vector of pointers.
Actually I have
Class A {
protected:
vector<Superobject*> vec;
...
};
Class B: public A {...};
Class Superobject {
protected:
int id;
...
}
Class Object: public Superobject {...}
In derived class B I want to fill the member field vec with objects of type Object. If the superclass didn't use pointers I would have problems with object slicing. So in class B constructor I want to initialize vec as vector of pointers of type Object*.
EDIT2
Yes, it seems to me that dynamic allocation is the reasonable option and the idea to use an array is a bad idea. When the array goes out of scope, things will go wrong because the pointers in vector point to memory locations that don't necessarily contain the objects anymore.
In constructor for class B I had
B(int n) {
vector<Object*> vec;
Object ar[n];
for(int id=0; id<n; id++) {
ar[id] = Object(id);
}
for(int id=0; id<n; id++) {
v.push_back(ar+id);
}
}
This caused very strange behavior in objects of class B.
In this loop:
for(int id=0; id<n; id++) {
Object ob = Object(id);
v.push_back(&ob);
}
You are creating n times Object instance on stack. At every iteration there is created and removed element. You can simply avoid this using that:
for(int id=0; id<n; id++) {
Object* ob = new Object(id);
v.push_back(ob);
}
thanks that every new element exist on heap not on the stack. Try to add to in class Object constructor something like that:
std::cout<<"Object ctor()\n";
and the same in the destructor:
std::cout<<"Object dtor()\n";
If you dont want to create these objects with "new" try reason written by #woolstar
Your question about memory leaks makes me think you are worried about the lifecycle and cleanup of these objects. I originally proposed shared_ptr wrappers, but C++11 gave us unique_ptr, and C++14 filled in the missing make_unique. So with all that we can do:
vector<unique_ptr<SuperObject>> v ;
Which you create in place with the wonderfulness of perfect forwarding and variadic templates,
v.push_back( make_unique<Object>( ... ) ) ;
Yes you are going to have to live with some heap allocations, but everything will be cleaned up when v goes away.
Someone proposed a boost library, ptr_container, but that requires not only adding boost to your project, but educating all future readers what this ptr_container is and does.
No there is no memory leak in your version. When the program leaves your scope the vector as well the array are destroyed. To your second question: Why not simply store the objects directly in an vector?
vector<Object> v;
for(int i = 0; i < n; i++)
{
Object obj = Object(i);
v.push_back(obj);
}

Do i have to delete wchar_t that i allocated with new?

Lets say i have a class like this:
class LolClass {
LPWSTR* stuff;
LolClass::LolClass(LPWCHAR lols) {
stuff = new LPWSTR[100];
for (int i = 0; i < 100; i++) {
stuff[i] = new wchar_t[wcslen(lols)+1];
wcsncpy(stuffs[i], lols, wcslen(lols)+1);
}
}
LolClass::~LolClass() {
delete[] stuff;
}
}
so if i call
LolClass* veryfunny = new LolClass(L"lol!");
it would make me 100 lol's, problem is when i call
delete veryfunny;
it deletes the pointer array but not the individual wchar_t's, if i try and loop through the wchar_t's and delete them then i just crash and i dont know what to do since i know for fact that they are still there even after i delete veryfunny (i checked by passing one of the pointers outside the class)
Thanks!
If you call
LolClass* veryfunny = new LolClass(L"lol!");
then you will eventually need to call:
delete veryfunny;
But for arrays, you need delete[]: stuff[i] = new wchar_t[n]; delete [] stuff[i];
In your code, you need to first loop over stuff and delete[] the elements, and then delete[] the array stuff itself.
Or just use a std::vector<std::wstring>.
Update: From what I understand, you're not actually worried about deleting *veryfunny, but rather about how to write a correct destructor for LolClass. Note that the destructor also gets invoked for global and automatic objects, e.g. { LolClass x(L"hello"); } /* boom */, so it doesn't really matter how you instantiate an object for LolClass. You have to get the class right in any case.
David Schwartz wins after all, the wchar's didnt let themselves be deleted because they werent null terminated