1

I'm a bit rusty on C++, haven't used it for a while. So I need to make a data structure that can hold objects and do operations with them. Just like a array list. Now I first create and init a dynamic array of my class type :

Student* array_of_students = new Student[SIZE];

Then I create a Student object, say like this :

Student student(param1, param2, etc..);

I also provide a destructor since I use a lot of char pointers (I know I should use string but this is for learning purpose only.) where I delete number of pointers that hold some names.

~Student(){ /* delete filed1; etc */ }

Well, when I try to list those names, I get some random values, probably because pointers are deleted, meaning destructor is called, and even if I have reference to a particular object with array_of_students, those fields are destroyed and I don't have anything to display. This probably happens because Student instance goes out of scope and calls it's destructor.

So what is the solution in here? How can I hold them as long as array_of_students is alive?

I believe I need to define some sort of copy constructor that will copy that original student instance to a new copy that will be referenced by array_of_students. Your thoughts would be helpful.

EDIT :

class Student{

private :
   char *_name;

   public :

   Student(){}
   Student(char* name){

      _name = new char[strlen(name)];
      strcpy(_name, name); }

   char* getNaziv(){return _name;}
   ~Student(){delete _name;}

};

int main()
{
    Student* array_of_students = new Student[5];
    char input[100];
    for(int i = 0; i < 5; i++){
        cout << "Input name : "<<endl;
        cin >> input;
        Student tmp(input);
        array_of_students[i] = tmp;
    }

    for(int i = 0; i < 5; i++){

        cout <<"Name is : "<< array_of_students[i].getNaziv()<< endl;
    }
}
nhrnjic6
  • 171
  • 1
  • 1
  • 9
  • 3
    The C++ equivalent to (Java's) array list is [`std::vector`](http://en.cppreference.com/w/cpp/container/vector). Please refrain from using raw arrays :) – maddouri Oct 19 '15 at 19:36
  • 1
    Please provide a SSCCE. – Shoe Oct 19 '15 at 19:36
  • Like I said, am not allowed to use vectors. Only raw. – nhrnjic6 Oct 19 '15 at 19:38
  • 2
    @nhrnjic6 Who disallows that? God? Your mom? Without reasoning, I'd just close that as offtopic. – Bartek Banachewicz Oct 19 '15 at 19:42
  • 1
    Maybe at least use smart pointers to manage those raw arrays? – Emil Laine Oct 19 '15 at 19:44
  • 2
    You don't have to use `new` to create an object either. `Student array_of_students[SIZE];` works just fine. Please don't write Java in C++, it is not going to work. – Bo Persson Oct 19 '15 at 19:47
  • SIZE is all upper case so it should be a constant. Since it should be a constant, there is no need to dynamically allocate the array. `Student array_of_students[SIZE];` should be sufficient. – user4581301 Oct 19 '15 at 19:48
  • And Bo Persson types just a bit faster than I. – user4581301 Oct 19 '15 at 19:48
  • 1
    You're mixing incompatible ideas and doing too many "bad practice" things that we really can't follow what you're actually asking about in this question. Post some code that demonstrates an issue, or use your debugger, please. Also, everyone is convinced you are asking us to do your homework because of the "not allowed to use vector" comment. Writing your own code to do what std::vector does, then complaining about bugs, is just ... no. – Kenny Ostrom Oct 19 '15 at 19:52
  • src code is in edit. I know its bad, but my school requires it like that – nhrnjic6 Oct 19 '15 at 19:54
  • 1
    You forgot about the null terminator… And your school should probably turn it into a ___C___ course. – Emil Laine Oct 19 '15 at 19:55
  • this works when I delete destructor – nhrnjic6 Oct 19 '15 at 19:57
  • 1
    http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three – Giorgi Moniava Oct 19 '15 at 19:58
  • @nhrnjic6 Walk through it in a debugger. Without the destructor, you leak the memory `_name` is pointing to. Who (which object) owns the memory pointed to by the `_name` member? – Rob K Oct 19 '15 at 21:11
  • If you place output statements in places like the destructor (and possibly the constructor, although that's pretty obvious), it becomes clearer where these are called. If that's not where you want, you can change things in your loop until you have something that works. – chrisb2244 Oct 20 '15 at 00:08
  • Currently you create the object `tmp`. Then you copy `tmp` to the array. This operation just copy the pointer to the array. Then `tmp` is destroyed. Since the destructor destroyes the string, the pointer in the array is inavlid. You have to copy or move the string in this situation. std::string or std::shared_ptr would not cause this problems. Alternative you could use a assignment operator for your class. You may also want a copy constructor. Maybe you could also use a move operator. – JojOatXGME Oct 20 '15 at 00:20
  • If your school requires it to be like THAT, your teacher should resign immediately (unless it's some kind of cruel punishment). Unfortunately, it is all too common for teachers to enforce awful programming practices. By all means, code how you have to for class (heck, implement your own linked list if you may), but please, PLEASE make sure you *know* the correct approaches for any future programming you do. Yours, the C++ community, and anyone who has had to maintain/refactor codebases written by people like your teacher. – Jake Oct 20 '15 at 01:18
  • You are missing the point, but thanks for reply – nhrnjic6 Oct 20 '15 at 05:36

1 Answers1

0

Try not to use char arrays to store string, use instead std::string. And if it is possible, don't use new keyword to allocate memory, let C++ take care of allocation and deallocation of memory for you.

And don't use raw arrays of Students, it's preferred to use std::vector or other container classes. Like this:

#include <cstdlib>
#include <iostream>
#include <vector>

class Student
{
        private :
                std::string _name;

        public :
                Student ( );
                Student ( std::string& name );

                void name ( std::string& );
                std::string& name ( );
};

Student::Student ( )
{
        /* Constructor with no parameters, do some crazy stuff... */
}

Student::Student ( std::string& name )
{
        this -> name ( name );
}

void Student::name ( std::string& name )
{
        this -> _name = name;
}

std::string& Student::name ( )
{
        return ( this -> _name );
}

int main ( int argc, char **argv )
{
        std::vector<Student> array_of_students;
        std::string input;

        for(int i = 0; i < 5; i++)
        {
            std::cout << "Input name : " << std::endl;
            std::cin >> input;

            Student tmp ( input );
            array_of_students.push_back ( tmp );
        }

        for( auto sit = array_of_students.begin ( ); sit != array_of_students.end ( ); ++ sit )
        {
                std::cout <<"Name is : "<< ( *sit ).name ( ) << std::endl;
        }

        return ( EXIT_SUCCESS );
}

Output:

Input name :
Name_01
Input name : 
Name_02
Input name : 
Name_03
Input name : 
Name_04
Input name : 
Name_05
Name is : Name_01
Name is : Name_02
Name is : Name_03
Name is : Name_04
Name is : Name_05
BufferOverflow
  • 543
  • 3
  • 12