在 ostream 中使用迭代器失败
using iterator in ostream fails
我正在尝试实现 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() << " students\n";
// 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
离开 rails 这里:
students[i] = *pos;
将 list
中的学生复制到动态数组 students
中。这可能很昂贵,所以这里有一个替代方案:
首先需要证明这一点的点点滴滴:必需包括
#include <iostream>
#include <list>
#include <vector>
#include <algorithm>
#include <functional>
最小学生class
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
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::copy
和 std::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() << " students\n";
// 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 迭代器实现为 return 个学生迭代器。
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();
}
我正在尝试实现 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() << " students\n";
// 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
离开 rails 这里:
students[i] = *pos;
将 list
中的学生复制到动态数组 students
中。这可能很昂贵,所以这里有一个替代方案:
首先需要证明这一点的点点滴滴:必需包括
#include <iostream>
#include <list>
#include <vector>
#include <algorithm>
#include <functional>
最小学生class
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
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::copy
和 std::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() << " students\n";
// 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 迭代器实现为 return 个学生迭代器。
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();
}