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

Pau*_*ams 0 c++ pointers vector

在我的代码中,我有一个Student对象的向量.

vector<Student> m_students;
Run Code Online (Sandbox Code Playgroud)

我想要:

  1. 检查向量是否包含任何具有某个名称的学生.
  2. 如果不存在此类学生,请添加新学生.
  3. 将数据添加到该名称的学生.

请考虑以下代码:

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

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

tor*_*que 9

在将对象插入向量后获取指向该对象的指针,而不是

targetStudent = new Student(strName);
m_students.push_back(*targetStudent);

使用

m_students.push_back(Student(strName));
targetStudent = &m_students.back();

另请注意,您的示例泄漏内存,从未删除复制到向量中的targetStudent.

此外,请记住,添加新元素时,向量中的指针变为无效(如果向量以光学大小增加,并且元素必须复制到新的更大的向量中,所有指向前一个缓冲区的指针都将变为无效).


Chr*_*ung 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);
}
Run Code Online (Sandbox Code Playgroud)

std::shared_ptr<memory>在C++ 11 的头文件中定义.(在TR1中,您可以std::tr1::shared_ptr改为使用.)如果您使用的是不带TR1的C++ 98,或者需要随身携带,那么您可以使用boost::shared_ptr; 从Boost下载.

  • 从理论上讲,你是对的.在实践中,惯例是没有正确思想的人会使用`std`作为命名空间. (2认同)

Jer*_*fin 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;
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++,但这并不是你应该期望的.