C++에서 객체 배열 질문드립니다.
안녕하세요 C++ 배운지 얼마 안 된 학생입니다.
C++로 간단한 카드 게임을 구현해 보려고 하는데, 카드 정렬 단계에서 모르는 부분이 있어서 질문 드리겠습니다.
일단 제가 짰던 코드를 단순화 해서 올리겠습니다.
#include <algorithm> #include <iostream> class myclass { private: int a; int b; public: // constructor myclass(int _a, int _b) : a(_a), b(_b) {} // copy constructor myclass(const myclass& other) : a(other.a), b(other.b) {} friend std::ostream& operator<<(std::ostream& out, const myclass mc) { out << "{" << mc.a << ", " << mc.b << "}"; return out; } }; class sortclass { private: myclass* arr[10]; int num; public: // constructor sortclass() : num(0) {} void sorting() { // 질문드릴 부분! } sortclass& operator+(const myclass& other) { arr[num++] = new myclass(other); return *this; } friend std::ostream& operator<<(std::ostream& out, const sortclass sc) { for(int i = 0; i < sc.num; i++) out << *sc.arr[i] << ((i < sc.num-1) ? ", ":""); return out; } };
myclass 객체가 a, b라는 두 개의 정수 인수를 갖고 있을 때, myclass 객체 배열을 우선 a에 대해 작은 숫자부터 정렬하고, a가 같은 값일 경우 b에 대해 작은 숫자부터 정렬하는 함수를 작성하고 싶습니다.
예를 들어 main함수가 아래와 같은 경우,
int main() { myclass* mc[10]; sortclass sc; int a[10][2] = {{3, 1}, {4, 2}, {2, 5}, {1, 3}, {3, 2}, {3, 5}, {4, 4}, {1, 1}, {2, 2}, {3, 3}}; for(int i = 0; i < 10; i++) { mc[i] = new myclass(a[i][0], a[i][1]); sc + *mc[i]; // Input mc[i] into sc.arr[i] (operator+ called) } cout << sc; // {3, 1}, {4, 2}, {2, 5}, {1, 3}, {3, 2}, {3, 5}, {4, 4}, {1, 1}, {2, 2}, {3, 3} sc.sorting(); cout << sc; // {1, 1}, {1, 3}, {2, 2}, {2, 5}, {3, 1}, {3, 2}, {3, 3}, {3, 5}, {4, 2}, {4, 4} }
위 주석과 같은 식으로 출력이 되게끔 말이죠.
http://stackoverflow.com/questions/12823573/c-sorting-class-array <- 이 문서를 보고 void sortclass::sorting() 함수를 아래와 같이 짜보았습니다.
std::sort(*arr, *(arr + num));
또한 위 링크에 나온 방법대로 myclass 클래스에 operator<을 오버로딩하여 myclass에 아래와 같은 함수를 삽입했습니다.
bool operator<(const myclass& rhs) { if(a == rhs.a) // If values of a are same, sort by value of b. return (b < rhs.b); return (a < rhs.a); }
빌드까지는 잘 되는데, 실행을 하면 invalid iterator range 에러가 뜨더군요.
VS의 한 줄 한 줄 읽어가며 컴파일 하는 기능으로 확인해 본 결과, algorithm 헤더파일 내에서 sort의 피벗 값을 구하기 위한 중간과정에서, myclass 클래스끼리의 덧셈/뺄셈 등의 연산이 들어가 이상한 변수들이 피벗값에 들어가는 것 같더군요.
그래서 myclass들끼리의 +-/연산자 등을 오버로딩 해봤는데 아예 호출이 되지 않더군요=_=;;
혹시 제가 너무 조잡하게 했는지, 다른 방법이 있는지, 수정해야 한다면 어디를 수정해야 하는지 설명해주시면 감사하겠습니다.
//ps: 후 그냥 벡터 쓰는 게 낫겠군요. 그래도 클래스 오브젝트를 sort에 직접 넣는 방식으로 해결하는 방법이 혹 없을까 궁금합니다.
문제는..
myclass* mc[10]을 선언하고 내부는 그 밑에서 new myclass()로 동적할당을 합니다.
이 상태로는 sort함수가 각각의 멤버 위치를 정확하게 찾아낼 수가 없습니다. 10개의 오브젝트의 메모리가 모두 동적할당되기 때문입니다.
예를 들어, mc[10]이 각각의 오브젝트용으로 할당받은 주소가 다음과 같다 합시다.
mc[0] = 0x10000;
mc[1] = 0x20000;
mc[2] = 0x15000;
....
mc[9] = 0x05000;
이런식으로 할당이 되었다 치고, sort함수가 처음 주소와 끝 주소인 0x10000과 0x05000을 전달받았다 칩시다. sort함수는 이렇게 주어진 두 개의 주소로 나머지 영역또한 접근합니다. 따라서 이 경우에는 나머지 값들을 읽을 방법이 없는 것입니다. 일반적인 배열, 즉 myclass mc[10]으로 선언하고 sort(&mc[0], &mc[9])로 하면 잘 동작할 겁니다. 각 배열의 멤버들이 연속적인 공간에 존재하기 때문입니다. 해당 배열 자체는 물론 동적으로 생성해도 무방합니다. 아니면 본문대로 그냥 구현을 하되, 소트 함수가 해당 공간에 대해 연속적으로 접근할 수 있게 추가적인 처리를 해주어도 됩니다만, 그럴거면 말씀하신 대로 벡터를 쓰는 게 더 낫겠죠.
마지막으로, 본문 소스에서 sort를 호출할때 사용한 인자도 잘못된 것 같네요. 저렇게 하면 arr이 가진 메모리 범위 이외의 영역을 전달하게 될 듯. 예를 들어 배열 크기가 10일때 arr[0], arr[10]을 전달하게 되겠네요.
--
정말 감사합니다!
정말 감사합니다!
댓글 달기