I'm new in c++ and I come from Java. So I have guess about modifying class members through reference variables.
In java to add an element to an existing list(class member) only have to use the "add" method, and that is all, but here I don't understand why I can't modify the vector with my get method.
class Student {
public:
Student(std::string n):name(n){};
std::string getName(){return name;};
void setName(std::string name){this->name = name;};
private:
std::string name;
};
class Subject {
public:
std::vector<Student> getStudents(){return students;};
void setStudents(std::vector<Student> students){this->students = students;};
private:
std::vector<Student> students;
};
int main() {
// Students
Student s1("Abi");
Student s2("Nat");
Student s3("Osi");
// normal case
Subject math;
std::vector<Student> students;
students.push_back(s1);
math.setStudents(students);
math.getStudents().push_back(s2);
// print names
for(unsigned int i=0; i < math.getStudents().size();i++) {
std::cout << math.getStudents()[i].getName() << std::endl;
}
// pointers
std::cout << "Ptr------------------" << std::endl;
Subject *mathPtr;
mathPtr = &math;
// try to add student to the existing vector
mathPtr->getStudents().push_back(s2); // it doesnt work
// it works if i add a new vector
std::vector<Student> studentsPtr;
studentsPtr = mathPtr->getStudents();
studentsPtr.push_back(s2);
mathPtr->setStudents(studentsPtr);
// print students of original object
for(unsigned int i=0; i < math.getStudents().size();i++) {
std::cout << math.getStudents()[i].getName() << std::endl;
}
// pointers
std::cout << "Smart_ptr-------------" << std::endl;
std::shared_ptr<Subject> mathSmartPtr;
mathSmartPtr = std::make_shared<Subject>(math);
// try to add student to the existing vector
mathSmartPtr->getStudents().push_back(s3); //it doesnt work
std::vector<Student> studentsSmartPtr;
studentsSmartPtr = mathPtr->getStudents();
studentsSmartPtr.push_back(s3);
mathSmartPtr->setStudents(studentsSmartPtr);// it doesnt work too
// print students of original object
for(unsigned int i=0; i < math.getStudents().size();i++) {
std::cout << math.getStudents()[i].getName() << std::endl;
}
}
I don't understand why the smart pointer doesn't work. It suppose to be as a normal pointer + autodelete, no?
Greetings and thanks.
The problem in your code is that you are making a lot of copies of the student vector, without realizing it. A common problem when you come from Java.
Specifically, in your Subject class, the method getStudents does not do what you probably think it does:
std::vector<Student> getStudents(){return students;};
It makes a copy of the vector called "students", and returns the copy to you, not the original. The same is also happening elsewhere in your code, but probably with less harmful effects.
You could easily fix this by including the reference operator:
std::vector<Student>& getStudents(){return students;};
will work just as it would in Java. There is a danger, though: if your Subject object is destroyed, the vector will go with it - even if you stored a reference to it elsewhere. For instance, this may crash your program:
Subject* mathPtr = new Subject;
// try to add student to the existing vector
std::vector<Student>& s = mathPtr->getStudents();
delete mathPtr;
s.push_back(s2); // accesses already-freed memory