在 ostream 中使用迭代器失败

using iterator in ostream fails

本文关键字:迭代器 失败 ostream      更新时间:2023-10-16

我正在尝试实现一个std::list来替换此作业中的链表。我不允许更改声明,只能更改.cpp文件中的代码。在大多数情况下,我正在取得进展,但我在实施时遇到了麻烦

std::ostream& operator<< (std::ostream& out, const Section& section);

也就是说,当我尝试创建迭代器时,它失败了。我在代码的其他地方使用了迭代器,所以我不明白为什么它在这里失败,我相信这是因为它是私有的,但我不确定如何在不更改明确禁止的 .h 文件的情况下解决问题:

std::ostream& operator<< (std::ostream& out, const Section& section)
{
// 1. print the section header
out << setw(8) << left << section.getCourse()
<< setw(6) << left << section.getCallNumber();
out << ": " << section.getNumberOfStudents() << " studentsn";
// 2. collect the students, sort, and print
Student* students = new Student[section.getNumberOfStudents()];
{
int i = 0;
for ( auto pos = section.students.begin();
pos != section.students.end(); pos++)
{
students[i] = pos;
++i;
}
}
sort (students, students+section.getNumberOfStudents());
for (int i = 0; i < section.getNumberOfStudents(); ++i)
out << "    " << students[i] << "n";
out << flush;
return out;
}
students[i] = pos;

应改为

students[i] = *pos;

因为您要复制迭代器引用Student,而不是迭代器本身。

但是为什么是动态的Student数组而不是std::vector<Student>?当前您有内存泄漏,因为您没有delete[] students;

编辑 1

删除。

编辑 2

除此之外,我只能看到它错了,就是眼前的std::缺失。

sort (students, students+section.getNumberOfStudents());

这是假设没有使用自定义sort方法。

编辑 3

在这里脱轨:

students[i] = *pos;

将学生从list复制到动态数组students中。这可能很昂贵,所以这里有一个替代方案:

首先,证明这一点所需的点点滴滴:必需的包括

#include <iostream>
#include <list>
#include <vector>
#include <algorithm>
#include <functional>

最小的学生班

class Student
{
std::string name; 
public:
Student(std::string inname):name(inname)
{
}
const std::string & getname() const
{
return name;
}
friend bool operator<(const Student & a, const Student &b)
{
return a.name < b.name;
}
};

最小的节类

class Section
{
public:
std::list<Student> students;
};

最小的外流运营商

std::ostream& operator<<(std::ostream& out, const Section& section)
{

一个std::vector而不是数组,以及一个常量引用的向量,所以我们不必复制学生。

std::vector<std::reference_wrapper<const Student>> students;

将引用存储在vector中。可能可以做一个带有std::copystd::back_inserter的衬里,但这对于一个例子来说有点太多了。

for (const auto & student: section.students)
{
students.push_back(std::ref(student));
}

vector进行排序

std::sort(students.begin(), students.end());

打印vector

for (const auto & student: students)
{
out << student.get().getname() << " ";
}
return out;
}

一个main统治他们所有人,并在黑暗中束缚他们

int main()
{
Section s;
s.students.emplace_front("Tom");
s.students.emplace_front("Dick");
s.students.emplace_front("Harry");
std::cout << s;
}

并且多合一,易于剪切粘贴:

#include <iostream>
#include <list>
#include <vector>
#include <algorithm>
#include <functional>
class Student
{
public:
std::string name; // this is me being lazy. name should be private
Student(std::string inname):name(inname)
{
}
const std::string & getname() const
{
return name;
}
friend bool operator<(const Student & a, const Student &b)
{
return a.name < b.name;
}
};
class Section
{
public:
std::list<Student> students;
};
std::ostream& operator<<(std::ostream& out, const Section& section)
{
std::vector<std::reference_wrapper<const Student>> students;
// store references in the `vector`.
for (const auto & student: section.students)
{
students.push_back(std::ref(student));
}
// Sort the `vector`
std::sort(students.begin(), students.end());
// print the `vector`
for (const auto & student: students)
{
out << student.get().getname() << " ";
}
return out;
}
int main()
{
Section s;
s.students.emplace_front("Tom");
s.students.emplace_front("Dick");
s.students.emplace_front("Harry");
std::cout << s;
}

或者按照 Remy 的建议进行操作,并使用std::vector<Student *>和自定义比较器来取消引用std::sort指针。

正如其他人所说,错误是因为您在填充students[]数组时没有取消引用迭代器:

students[i] = pos; // <-- should be *pos instead!

我建议一种更快、更有效的替代方法:

std::ostream& operator<< (std::ostream& out, const Section& section)
{
// 1. print the section header
out << setw(8) << left << section.getCourse()
<< setw(6) << left << section.getCallNumber();
out << ": " << section.getNumberOfStudents() << " studentsn";
// 2. collect the students, sort, and print
std::vector<const Student*> students;
students.reserve(section.getNumberOfStudents());
for ( auto pos = section.students.cbegin();
pos != section.students.cend(); ++pos)
{
students.push_back(&(*pos));
}
sort (students.begin(), students.end(), 
[](const Student *a, const Student *b) { return (*a < *b); }
);
for ( auto pos = students.cbegin();
pos != students.cend(); ++pos)
{
out << "    " << *(*pos) << "n";
}
out << flush;
return out;
}

感谢您的所有回答。最终成为一个更基本的问题。我必须实现部分迭代器以返回学生迭代器。

Section::iterator Section::begin() {
return students.begin();
}
Section::const_iterator Section::begin() const {
return students.begin();
}
Section::iterator Section::end() {
return students.begin();
}
Section::const_iterator Section::end() const {
return students.begin();
}