Search code examples
c++arraysdynamic-memory-allocation

Using an array of pointers to objects that require variables passed in


I have 3 files. main.cpp, object.h, and object.cpp.

In main I am trying to create an array of 100 object pointers. Then, after creating the array I enter a loop and go through each 'i' element and assign the value of that element as the pointer to a new temporary object which will be passed in a string. The basic premise of this is that I can use this to store multiple objects which have information inside them, information that I can print afterwards by calling a function on those points. I'm required to use an array of pointers to do so.

In essence, I want to store data in an array of object pointers which will use a new operator to store it each iteration. However, I'm not sure how to even create the array since it needs to be passed in variables to be called.

I've tried Object *ptr = new Object[arraySize]; and I was sure that would work but it expects arguments since the object is defined to take variables inside it.

main.cpp

#include <iostream>
#include "object.h"

int main()
{
    Object *ptr = new Object[5];
    for(i = 0; i < 5, i++) {
        ptr[i] = "Test";
        ptr -> print();
    }

}

object.cpp

#include "object.h"
#include <iostream>

using namespace std;

Object::Object(string words)
{
    private_words = words;
}

void Object::print()
{
    cout << private_words << endl;
}

object.h

#ifndef OBJECT_H
#define OBJECT_H

#include <string>

using namespace std;

class Object
{

    public:
        Object(string words);
        void print();
    private:
        string private_words;
};

#endif

I got multiple unintelligible errors about the fact that I tried to pass in arguments and make it an array at the same time. Object *ptr = new Object()[5] didn't work.


Solution

  • Your Object class lacks a default constructor, which is why new Object[...] will not work. You will have to use something more like this instead:

    #include <iostream>
    #include "object.h"
    
    int main()
    {
        Object **ptr = new Object*[5];
        for(i = 0; i < 5, i++) {
            ptr[i] = new Object("Test");
        }
    
        // use ptr as needed ...
    
        for(i = 0; i < 5, i++) {
            ptr[i]->print();
        }
    
        // cleanup ...
    
        for(i = 0; i < 5, i++) {
            delete ptr[i];
        }
        delete[] ptr;
    }
    

    Better would be to use standard containers instead and let the compiler manage the memory for you.

    Prior to C++11:

    #include <iostream>
    #include <memory>
    #include "object.h"
    
    int main()
    {
        // NOTE: std::auto_ptr is NOT a container-safe type...
        std::auto_ptr<Object>* ptr = new std::auto_ptr<Object>[5];
        for(i = 0; i < 5, i++) {
            ptr[i].reset(new Object("Test"));
        }
    
        // use ptr as needed ...
    
        for(i = 0; i < 5, i++) {
            ptr[i]->print();
        }
    
        // cleanup ...
        // only the array is needed manually, the individual elements
        // will clean themselves up when they are destructed ...
    
        delete[] ptr;
    }
    

    In C++11 and later, use this instead:

    #include <iostream>
    #include <vector>
    #include <memory>
    #include "object.h"
    
    int main()
    {
        // NOTE: std::unique_ptr IS a container-safe type...
        std::vector<std::unique_ptr<Object>> ptr(5);
        for(i = 0; i < 5, i++) {
            ptr[i].reset(new Object("Test"));
    
            // or:
            // ptr[i] = std::unique_ptr<Object>(new Object("Test"));
    
            // or, in C++14 and later:
            // ptr[i] = std::make_unique<Object>("Test");
        }
    
        // use ptr as needed ...
    
        for(i = 0; i < 5, i++) {
            ptr[i]->print();
        }
    
        // all cleanup is automatic when ptr goes out of scope ...
    }