对象的排序向量接收堆栈溢出异常C++
Sort vector of object receive stack overflow exception c++
我正在尝试按属性对 Student
个对象的向量进行排序:
class Student
{
private:
std::string nume;
int an;
std::list<Curs> cursuri;
...
public:
Student();
Student(std::string nume, int an);
virtual ~Student();
...
};
使用这些排序方法比较器:
bool Student::sortByMedie(const Student& a, const Student& b)
{
return a.medie < b.medie;
}
void sortStudenti(std::vector<Student> studenti) {
std::sort(studenti.begin(), studenti.end(), Student::sortByMedie);
for (auto student : studenti) {
student.afisare();
}
}
但是调用sort方法时遇到堆栈溢出异常的问题:
The thread 0x4f6c has exited with code 0 (0x0). Exception thrown at 0x776CBA3E (ntdll.dll) in LAB3.exe: 0xC00000FD: Stack overflow (parameters: 0x00000001, 0x01002FF0). Unhandled exception at 0x776CBA3E (ntdll.dll) in LAB3.exe: 0xC00000FD: Stack overflow (parameters: 0x00000001, 0x01002FF0).
我假设问题出在内存中向量大小的重新分配中。如果我浏览内存分配函数之外的堆栈跟踪,我自己的代码(即非标准库)的最后一个函数是一个 Curs
复制构造函数,由两个 Cusr
元素之间的交换调用,即由 Curs::operator=
调用
这是向量的创建:
std::vector<Student> studenti;
auto student1 = Student("gigel marian", 3);
student1.addCursuri(generateCoursList());
auto student2 = Student("gigel marian2", 3);
student2.addCursuri(generateCoursList());
auto student3 = Student("gigel marian3", 3);
student3.addCursuri(generateCoursList());
auto student4 = Student("gigel marian4", 3);
student4.addCursuri(generateCoursList());
auto student5 = Student("gigel marian5", 3);
student5.addCursuri(generateCoursList());
studenti.push_back(student1);
studenti.push_back(student2);
studenti.push_back(student3);
studenti.push_back(student4);
studenti.push_back(student5);
首先我尝试了这个方法:
void sortStudenti(std::vector<Student> studenti) {
struct studentCompare
{
bool operator()(Student const& a, Student const& b)
{
return a.getMedie() > b.getMedie();
}
};
std::sort(studenti.begin(), studenti.end(), studentCompare());
for (auto student : studenti) {
student.afisare();
}
}
但是我遇到了一些 const
访问错误,所以我尝试了另一种方式。
编辑:附加代码
完整代码可在 github
您可以通过引用传递您的向量,而不更改您的对象,方法是通过 const
引用将它们传递给循环,如下所示。
但是要确保成员函数afisare
是const
void sortStudenti(std::vector<Student>& studenti) {
struct studentCompare
{
bool operator()(Student const& a, Student const& b)
{
return a.getMedie() > b.getMedie();
}
};
std::sort(studenti.begin(), studenti.end(), studentCompare());
for (const auto& student : studenti) {
student.afisare();
}
}
但我认为还有一个例外的原因。你应该检查你的class定义
当 sort()
尝试交换 Student
元素时,它会制作 Student
元素的临时副本。由于您没有指定任何其他内容,因此将执行默认的逐个成员复制。
在您的 Student
class 中,您有一个列表 Curs
。该列表与它包含的 Curs
元素一起复制。但是对于 Curs,您已经定义了自己的赋值运算符:
Curs& Curs::operator=(Curs arg) noexcept
{
std::swap(*this, arg);
return *this;
}
生成的 swap()
后面的代码让您再次复制 Curs,这将再次调用交换和 Curs,....等等,直到堆栈溢出或内存用完。
顺便说一句,我看到您创建此运算符是为了规避 Curs class 包含的 const 成员背后的限制。以这种方式欺骗编译器来更改 const 元素是未定义的行为。因此,摆脱需要复制的成员的常量。
只需摆脱这个(错误实现的)运算符和常量,它就会起作用。
其他建议
这个问题确实是一个复杂的问题,只需要摘录一些代码就可以解决。特别是当问题不在我们认为的地方时。所以以后只能推荐你了:
充分利用您掌握的错误信息
- Post 您问题中的完整错误消息。
- 在堆栈溢出的情况下:浏览堆栈跟踪,直到找到您的一些代码,看看它发生在代码的哪一部分。这有助于缩小研究范围。
- 如果你多浏览一点,你还可以检查是否存在无限递归(数据量小的堆栈溢出最常见的原因):很长的连续几乎相同的调用是一个典型的症状.
减少出错的风险
- 在开始构建更复杂的 classes 之前,进行测试以确保底层 classes 能够按预期工作。
- 即使您没有足够的时间编写大量测试,您也应该至少尝试每个 class 成员函数。如果你做了一个只检查
Curs::operator=
是否有效的测试,你就会节省很多额外的实验;-)
我正在尝试按属性对 Student
个对象的向量进行排序:
class Student
{
private:
std::string nume;
int an;
std::list<Curs> cursuri;
...
public:
Student();
Student(std::string nume, int an);
virtual ~Student();
...
};
使用这些排序方法比较器:
bool Student::sortByMedie(const Student& a, const Student& b)
{
return a.medie < b.medie;
}
void sortStudenti(std::vector<Student> studenti) {
std::sort(studenti.begin(), studenti.end(), Student::sortByMedie);
for (auto student : studenti) {
student.afisare();
}
}
但是调用sort方法时遇到堆栈溢出异常的问题:
The thread 0x4f6c has exited with code 0 (0x0). Exception thrown at 0x776CBA3E (ntdll.dll) in LAB3.exe: 0xC00000FD: Stack overflow (parameters: 0x00000001, 0x01002FF0). Unhandled exception at 0x776CBA3E (ntdll.dll) in LAB3.exe: 0xC00000FD: Stack overflow (parameters: 0x00000001, 0x01002FF0).
我假设问题出在内存中向量大小的重新分配中。如果我浏览内存分配函数之外的堆栈跟踪,我自己的代码(即非标准库)的最后一个函数是一个 Curs
复制构造函数,由两个 Cusr
元素之间的交换调用,即由 Curs::operator=
这是向量的创建:
std::vector<Student> studenti;
auto student1 = Student("gigel marian", 3);
student1.addCursuri(generateCoursList());
auto student2 = Student("gigel marian2", 3);
student2.addCursuri(generateCoursList());
auto student3 = Student("gigel marian3", 3);
student3.addCursuri(generateCoursList());
auto student4 = Student("gigel marian4", 3);
student4.addCursuri(generateCoursList());
auto student5 = Student("gigel marian5", 3);
student5.addCursuri(generateCoursList());
studenti.push_back(student1);
studenti.push_back(student2);
studenti.push_back(student3);
studenti.push_back(student4);
studenti.push_back(student5);
首先我尝试了这个方法:
void sortStudenti(std::vector<Student> studenti) {
struct studentCompare
{
bool operator()(Student const& a, Student const& b)
{
return a.getMedie() > b.getMedie();
}
};
std::sort(studenti.begin(), studenti.end(), studentCompare());
for (auto student : studenti) {
student.afisare();
}
}
但是我遇到了一些 const
访问错误,所以我尝试了另一种方式。
编辑:附加代码
完整代码可在 github
您可以通过引用传递您的向量,而不更改您的对象,方法是通过 const
引用将它们传递给循环,如下所示。
但是要确保成员函数afisare
是const
void sortStudenti(std::vector<Student>& studenti) {
struct studentCompare
{
bool operator()(Student const& a, Student const& b)
{
return a.getMedie() > b.getMedie();
}
};
std::sort(studenti.begin(), studenti.end(), studentCompare());
for (const auto& student : studenti) {
student.afisare();
}
}
但我认为还有一个例外的原因。你应该检查你的class定义
当 sort()
尝试交换 Student
元素时,它会制作 Student
元素的临时副本。由于您没有指定任何其他内容,因此将执行默认的逐个成员复制。
在您的 Student
class 中,您有一个列表 Curs
。该列表与它包含的 Curs
元素一起复制。但是对于 Curs,您已经定义了自己的赋值运算符:
Curs& Curs::operator=(Curs arg) noexcept
{
std::swap(*this, arg);
return *this;
}
生成的 swap()
后面的代码让您再次复制 Curs,这将再次调用交换和 Curs,....等等,直到堆栈溢出或内存用完。
顺便说一句,我看到您创建此运算符是为了规避 Curs class 包含的 const 成员背后的限制。以这种方式欺骗编译器来更改 const 元素是未定义的行为。因此,摆脱需要复制的成员的常量。
只需摆脱这个(错误实现的)运算符和常量,它就会起作用。
其他建议
这个问题确实是一个复杂的问题,只需要摘录一些代码就可以解决。特别是当问题不在我们认为的地方时。所以以后只能推荐你了:
充分利用您掌握的错误信息
- Post 您问题中的完整错误消息。
- 在堆栈溢出的情况下:浏览堆栈跟踪,直到找到您的一些代码,看看它发生在代码的哪一部分。这有助于缩小研究范围。
- 如果你多浏览一点,你还可以检查是否存在无限递归(数据量小的堆栈溢出最常见的原因):很长的连续几乎相同的调用是一个典型的症状.
减少出错的风险
- 在开始构建更复杂的 classes 之前,进行测试以确保底层 classes 能够按预期工作。
- 即使您没有足够的时间编写大量测试,您也应该至少尝试每个 class 成员函数。如果你做了一个只检查
Curs::operator=
是否有效的测试,你就会节省很多额外的实验;-)