2016-06-08 118 views
0

我正在嘗試實現std :: list來替換此分配中的鏈接列表。我不能更改聲明,只能更改.cpp文件中的代碼。在大多數情況下,我正在取得進展,但我遇到了困難在ostream中使用迭代器失敗

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; 
} 
+0

新列表類型沒有公開方法逐元素訪問? –

+0

我想我有答案,但我刪除它,直到我可以確認'section.students.begin()'返回'std :: list :: Iterator '。 – user4581301

+2

'section'是const,所以你可能需要'section.students.cbegin()'和'section.students.cend()'。 – kfsone

回答

2
students[i] = pos; 

,因爲你要複製的Student迭代器引用,而不是迭代器本身應改爲

students[i] = *pos; 

但爲什麼動態數組的Student而不是std::vector<Student>?目前,你有內存泄漏,因爲你不delete[] students;

編輯1

刪除。

編輯2

除此之外,所有我可以看到它的錯誤在於

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

這個前提是在不使用任何定製sort方法前丟失std::

編輯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) 
{ 

A 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; 
} 

或者做什麼雷米建議,並使用std::vector<Student *>和一個自定義比較取消引用指針std::sort

+0

hrm仍然沒有骰子。我並不喜歡使用數組,他提到我們應該在現有的<<之前的實驗室之後對其進行建模,因此我以此爲出發點。將pos更改爲* pos沒有效果。我應該提到我得到的錯誤是「在這種情況下」,但section.h的std :: list 學生;聲明抱怨說:'std :: list Section :: students'是私人的「,我嘗試創建一個迭代器。我只是不確定如何從運營商<<訪問學生列表而不更改其聲明。 – Addy

+0

至於常見的問題迭代器在.h中聲明這樣不會自動處理使用正確的版本或我誤解如何自動工作? 'iterator begin();' 'const_iterator begin()const;' – Addy

+0

你讓我們在const迭代器上。不知道編譯器可以在'const'上選擇一個重載,但我可能應該有。它基於'const TYPE * this'參數進行選擇。 – user4581301

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