在C ++中,如何在保持指向对象的指针的同时将对象推送到向量?

时间:2009-10-12 03:04:18

标签: c++ pointers vector

在我的代码中,我有一个学生对象的向量。

vector<Student> m_students;

我想:

  1. 检查该向量是否包含任何具有某个名称的学生。
  2. 如果没有此类学生,请添加一个新学生。
  3. 向该名称的学生添加数据。
  4. 请考虑以下代码:

    // 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不会更改向量中包含的对象。

    我怎样才能从指向对象的指针开始,将该对象添加到向量中,然后访问向量中的对象?

3 个答案:

答案 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 ++,但这不是你应该期望的。