0

i'm trying to run insertion sort on a simple class of my own making, which features a couple fields (int, float, and string) as well as a copy constructor, assignment operator, and '>' operator.

however, i'm getting a stack overflow when i run the code below. visual studio tells me its coming from the getName() function in my 'Student' class. the error originates from the assignment in my insertion sort function arr[i + 1] = arr[i];

anyone know why this is? i'm relatively new to c++, coming from mostly a java background.

#include <iostream>
#include <vector>
#include <string>
using namespace std;

class Student {
public:
    Student(string nm, int ID, float avg): name(nm), studentID(ID), overallAverage(avg) {}

    Student(const Student& rhs) : name(rhs.getName()), studentID(rhs.getStudentID()), overallAverage(rhs.getOverallAverage()) {}

    // copy and swap idiom
    Student& operator=(const Student& rhs) {
        Student copy = rhs;  // places a copy of rhs into copy using the copy constructor (copy will be cleaned up on return)
        swap(*this, copy); // move copy or rhs into this, this is a pointer to current object, *this dereferences the pointer
        return *this; 
    }
    ~Student() {}

    bool operator>(const Student& rhs) {
        if (rhs.getOverallAverage() > overallAverage)
            return false;
        else return true; 
    }

    string getName()const { return name; }
    int getStudentID()const { return studentID;  }
    float getOverallAverage()const { return overallAverage; }

private:
    string name; 
    int studentID; 
    float overallAverage; 

};

template<typename T> 
vector<T>& insertionSort(vector<T>& arr){
    for (int j = 1; j < arr.size(); j++) {
        T key = arr[j]; 
        int i = j - 1; 
        while (i > -1 && arr[i] > key) {
            arr[i + 1] = arr[i]; 
            i = i - 1; 
        }
        arr[i + 1] = key; 
    }
    return arr; 
}


int main()
{
    vector<Student> students = {Student("russ",0,89),Student("Seb",1,75),Student("julia",2,85),
                                Student("johnny",3,90),Student("Sushma",4,55)}; 

    students = insertionSort(students); 

    for (int i = 0; i < students.size(); i++) {
        cout << students[i].getName() << ", ";
    }
    cout << endl;  
}

original operator= from txtbook i'm using:

IntCell & operator= ( const IntCell & rhs ) // Copy assignment
{
IntCell copy = rhs;
std::swap( *this, copy );
return *this;
}
6
  • 2
    Your operator = calls std::swap, which calls your operator =, which calls std::swap, which calls your operator =, which calls std::swap ... Commented Jan 11, 2020 at 21:23
  • really? i coped that operator= directly from a well-known c++ textbook : edit-> put the textbook's operator= at bottom of my original question Commented Jan 11, 2020 at 21:28
  • 1
    In that book, did the class have its own swap function? If so, that is what prevented the infinite recursion. The std::swap will use the class swap function. Commented Jan 11, 2020 at 21:30
  • ah, i see you're right. upon re-reading that section it mentions: "t. Notice that if swap were implemented using the basic copy algorithm in Figure 1.14, the copy-and-swap idiom would not work, because there would be mutual nonterminating recursion. In C++11 we have a basic expectation that swapping is implemented either with three moves or by swapping member by member" Commented Jan 11, 2020 at 21:34
  • A generic routine like std::swap requires that the arguments be Swappable, and obviously your Student class was not, until a custom Student::swap function is created. Commented Jan 11, 2020 at 21:44

1 Answer 1

2

The infinite recursion is caused by std::swap calling Student::operator=, which calls std::swap, which calls Student::operator=, etc.

To alleviate this, write your own swap function that calls std::swap on each of the members:

class Student
{
//...
   void swap(Student& left, Student& right)
    {
        std::swap(left.name, right.name);
        std::swap(left.studentID, right.studentID);
        std::swap(left.overallAverage, right.overallAverage);
    }
//...
};
Sign up to request clarification or add additional context in comments.

2 Comments

thanks. it works now. the std::swap didn't work (error - no instance of overloaded function std::swap matches the argument list) so i just did left.name = right.name, etc. is this bad?
See what std::swap expects the arguments to be.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.