Pau*_*ams 0 c++ pointers vector
在我的代码中,我有一个Student对象的向量.
vector<Student> m_students;
Run Code Online (Sandbox Code Playgroud)
我想要:
请考虑以下代码:
// 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);
Run Code Online (Sandbox Code Playgroud)
当我调用m_students.push_back(*targetStudent);
它时,似乎向量"m_students"最终得到了"targetStudent"当时指向的Student对象的副本.
后续尝试添加到targetStudent不会更改向量中包含的对象.
我怎样才能从指向对象的指针开始,将该对象添加到向量中,然后访问向量中的对象?
在将对象插入向量后获取指向该对象的指针,而不是
targetStudent = new Student(strName); m_students.push_back(*targetStudent);
使用
m_students.push_back(Student(strName)); targetStudent = &m_students.back();
另请注意,您的示例泄漏内存,从未删除复制到向量中的targetStudent.
此外,请记住,添加新元素时,向量中的指针变为无效(如果向量以光学大小增加,并且元素必须复制到新的更大的向量中,所有指向前一个缓冲区的指针都将变为无效).
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);
}
Run Code Online (Sandbox Code Playgroud)
std::shared_ptr
<memory>
在C++ 11 的头文件中定义.(在TR1中,您可以std::tr1::shared_ptr
改为使用.)如果您使用的是不带TR1的C++ 98,或者需要随身携带,那么您可以使用boost::shared_ptr
; 从Boost下载.
你已经对你的问题得到了合理直接的答案.然而,根据你似乎想要完成的事情,在我看来,一个不太直接的答案可能真的是一个更好的答案.
至少在我阅读你的描述时,你有许多独特的学生,每个学生都有很多课程.当学生完成课程后,您想要找学生.如果他们不在集合中,请添加它们.然后添加他们完成的课程的数据.
在这种情况下,一个向量让我感觉不太理想.您可以通过几种不同的方式实现代码,但我可能会这样做:
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;
Run Code Online (Sandbox Code Playgroud)
使用此选项,您的整个序列可以查找学生,如果没有该学生,则插入新学生,然后将课程作业添加到(新的或现有的)学生的记录中,其结果如下:
m_students[strName].push_back(course(strQuarter, strCourse, strCredits, strGrade));
Run Code Online (Sandbox Code Playgroud)
回到原始问题,标准容器旨在使用值.您将值传递给它们,并存储该值的副本.其中一个结果是,任何类似的东西push_back(new XXX)
本质上都是一个错误(几乎是一个保证内存泄漏).如果你有一个对象,只需传递它.如果你不这样做,只需创建一个临时的并传递它.在Java中(例如)看到new XXX
所有地方都是常规的,几乎是不可避免的.虽然你也可以用这种方式编写C++,但这并不是你应该期望的.