修改 class c++ 上的引用成员

Modify references members on class c++

我是 c++ 新手,来自 Java。所以我猜想通过引用变量修改class成员。

在java中添加一个元素到已有的列表中(class成员)只需要使用"add"方法,仅此而已,但我这里不用明白为什么我不能用我的 get 方法修改矢量。

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;
  }
}

我不明白为什么智能指针不起作用。它应该是一个普通的指针+自动删除,不是吗?

问候和感谢。

您的代码中的问题是您在没有意识到的情况下制作了很多学生向量的副本。来自 Java.

时的常见问题

具体来说,在您的主题 class 中,方法 getStudents 与您可能认为的不同:

std::vector<Student> getStudents(){return students;};

它制作了一个名为 "students" 的矢量副本,returns 将副本提供给您,而不是原始文件。同样的情况也发生在您代码的其他地方,但危害可能较小。

您可以通过包含引用运算符轻松解决此问题:

std::vector<Student>& getStudents(){return students;};

将像在 Java 中一样工作。但是,存在一个危险:如果您的 Subject 对象被销毁,向量将随之消失——即使您在别处存储了对它的引用。例如,这可能会使您的程序崩溃:

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

您已将 getStudents 声明为 return copy students 向量。

std::vector<Student> getStudents(){return students;};

所以当你这样做时:

getStudents().push_back(...)

它只会添加到矢量的副本,它会立即被销毁,因为您没有将它存储在任何地方。因此原始 students 向量不会被修改。

如果你想push_back到原始向量,你将需要return一个reference对它:

std::vector<Student>& getStudents(){return students;}; 
                    ^

这可能有帮助

 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:
        Student * getStudent(std::string name);
        void setStudents(Student* student);
        void PrintStudents();
    private:
        std::vector<Student*> students;
        typedef std::vector<Student*>::iterator iter;
    };

    Student* Subject::getStudent(std::string name)
    {
        Student* stud = NULL;
        for (iter i = students.begin(); i != students.end(); ++i)
        {
            if ((*i)->getName() == name)
                stud = (*i);
        }
        return stud;
    }

    void Subject::setStudents(Student* student)
    {
        students.push_back(student);
    }

    void Subject::PrintStudents()
    {
        for (iter i = students.begin(); i != students.end(); ++i)
        {
                std::cout << (*i)->getName() << std::endl;
        }
    }

    int main()
    {
        Student* s1;
        s1 = new Student("Kavinda");
        Student s2("Liza");

        Subject math;
        math.setStudents(s1);
        math.setStudents(&s2);

        Student *s3 = math.getStudent("Kavinda");
        if (s3)
            std::cout << s3->getName() << std::endl;
        else
            std::cout << "No Student Exists having that name\n" << std::endl;

        math.PrintStudents();

        getchar();
        return 0;
    }