在ostream中使用iterator失败

时间:2016-06-08 23:35:07

标签: c++ arrays stdlist

我正在尝试实现一个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;
}

3 个答案:

答案 0 :(得分:2)

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的指针。

答案 1 :(得分:1)

正如其他人所说,错误是因为在填充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;
}

答案 2 :(得分:0)

我感谢您的所有答案。结束是一个更基本的问题。我必须实现Section迭代器来返回学生迭代器。

    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();
}