修改类c++上的引用成员
Modify references members on class c++
我是c++新手,来自Java。所以我对通过引用变量修改类成员有一些猜测。
在java中,向现有列表(类成员)添加元素只需要使用"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中常见的问题。
具体来说,在Subject类中,getStudents方法不会做你可能认为它会做的事情:
std::vector<Student> getStudents(){return students;};
它生成一个名为"students"的向量副本,并将副本返回给您,而不是原始副本。同样的情况也发生在代码的其他地方,但可能危害较小。
您可以通过包含参考运算符来轻松解决此问题:
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
以返回students
向量的副本。
std::vector<Student> getStudents(){return students;};
所以当你这样做的时候:
getStudents().push_back(...)
它只会添加到向量的副本中,该副本会立即被销毁,因为您没有将其存储在任何位置。因此,原始CCD_ 3矢量不会被修改。
如果要将push_back
转换为原始矢量,则需要向其返回引用:
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 namen" << std::endl;
math.PrintStudents();
getchar();
return 0;
}
相关文章:
- 具有引用成员的结构是否具有唯一的对象表示形式
- 初始化右值引用成员
- C++通过绑定到引用成员而缩短临时变量寿命?
- C++为具有引用成员变量的类创建复制构造函数
- 常量和引用成员函数限定符
- C++将引用成员绑定到构造函数参数
- 如果包含引用成员的类中缺少原始变量,为什么它仍然可以访问?
- 初始化指针或引用成员变量以指向另一个成员
- 将常量引用成员设置为临时变量是否安全
- 对象超出范围后,引用成员设置为 0
- 复制构造函数初始化初始化列表中的引用成员会导致指针悬空
- 使用默认构造函数引用成员变量初始化错误
- 如何从派生类访问引用成员变量?
- Visual Studio 2017 允许在构造函数中使用自身初始化引用成员.真的是合法的C++吗?
- 为什么当类具有引用成员时C++编译器不删除复制构造函数
- 引用成员到构造函数参数按值传递
- 在执行不平凡的构造函数之前引用成员
- 具有引用成员变量的多态性
- 从按值构造函数参数初始化的引用成员
- 深度复制包含引用成员(C++)的结构