在我的代码中,我有一个学生对象的向量。
vector<Student> m_students;
我想:
请考虑以下代码:
// Check to see if the Student already exists.
Student* targetStudent = NULL;
for each (Student student in m_students)
{
if (student.Name() == strName)
{
targetStudent = &student;
break;
}
}
// If the Student didn't exist, add it.
if (targetStudent == NULL)
{
targetStudent = new Student(strName);
m_students.push_back(*targetStudent);
}
// Add the course info to the Student.
targetStudent->Add(strQuarter, strCourse, strCredits, strGrade);
当我调用m_students.push_back(*targetStudent);
时,似乎向量“m_students”最终带有“targetStudent”指向的Student对象的副本。
后续尝试添加到targetStudent不会更改向量中包含的对象。
我怎样才能从指向对象的指针开始,将该对象添加到向量中,然后访问向量中的对象?
答案 0 :(得分:9)
在将对象插入向量后获取指向对象的指针,而不是
targetStudent = new Student(strName); m_students.push_back(*targetStudent);
使用
m_students.push_back(Student(strName)); targetStudent = &m_students.back();
另请注意,您的示例泄漏了内存,从未删除复制到向量中的targetStudent。
此外,请记住,添加新元素时,向量中的指针变为无效(如果向量以光学大小增加,并且元素必须复制到新的更大的向量中,则所有指向前一个缓冲区的指针都将变为无效)。
答案 1 :(得分:6)
STL容器复制它们包含的对象。没有办法解决这个问题。
但是,您可以拥有一个std::vector<std::shared_ptr<Student> >
,它允许您拥有一个智能指针容器。但是,要使其工作,您的对象必须在构造时全部附加到shared_ptr
。
所以,比如:
std::vector<std::shared_ptr<Student> > m_students;
std::shared_ptr<Student> targetStudent;
for each (std::shared_ptr<Student> student in m_students)
{
if (student->Name() == strName)
{
targetStudent = student;
break;
}
}
// If the Student didn't exist, add it.
if (!targetStudent)
{
// creates a new Student and attaches it to smart pointer
targetStudent.reset(new Student(strName));
m_students.push_back(targetStudent);
}
std::shared_ptr
在C ++ 11的<memory>
标头中定义。 (在TR1中,您可以使用std::tr1::shared_ptr
代替。)如果您使用的是不带TR1的C ++ 98,或者需要随身携带,则可以使用boost::shared_ptr
代替;从Boost下载。
答案 2 :(得分:5)
您已经对问题有了合理直接的答案。然而,基于你似乎想要完成的事情,在我看来,一个不太直接的答案可能真的是一个更好的答案。
至少在我阅读你的描述时,你有许多独特的学生,每个学生都有很多课程。当学生完成课程后,您想要找学生。如果他们不在集合中,请添加它们。然后添加他们完成的课程的数据。
在这种情况下,一个向量让我感觉不太理想。您可以通过几种不同的方式实现代码,但我可能会这样做:
struct course {
std::string Quarter_, Course_, Credits_, Grade_;
using std::string;
course(string const &q, string const &c, string const &cr, string const &g)
: Quarter_(q), Course_(c), Credits_(cr), Grade_(g)
{}
};
std::map<std::string, std::vector<course> > m_students;
使用此选项,您的整个序列可以查找学生,如果没有该学生,则插入新学生,然后将课程作业添加到(新的或现有的)学生的记录中,其结果如下: p>
m_students[strName].push_back(course(strQuarter, strCourse, strCredits, strGrade));
回到原始问题,标准容器旨在使用值。您将值传递给它们,并存储该值的副本。其中一个结果就是像push_back(new XXX)
这样的东西基本上总是一个错误(几乎是保证内存泄漏)。如果你有一个对象,只需传递它。如果你不这样做,只需创建一个临时的并传递它。在Java中(例如)在整个地方看到new XXX
是常规的,几乎是不可避免的。虽然你也可以以这种方式编写C ++,但这不是你应该期望的。