c++ 질문입니다.
글쓴이: ozon1000 / 작성시간: 화, 2016/01/12 - 10:54오전
#include<iostream> #include<cstdlib> using namespace std; class Array1D { private: int* arr1; int len1; public: Array1D(int n = 0) : len1(n) { arr1 = new int[n]; } int& operator[](int index) { if (index < 0 || index >= len1) { cout << "Out of index range" << endl; exit(0); } return arr1<ol> </ol> ; } int Getlen() { return len1; } ~Array1D() { cout << "Array1" << endl; delete[]arr1; } }; class Array2D { private: Array1D* arr2; int len; public: Array2D(int n1, int n2) :len(n1) { arr2 = new Array1D[n1]; for (int i = 0; i < n1; i++) arr2[i] = Array1D(n2); } Array1D& operator[](int index) { if (index < 0 || index >= len) { cout << "Out of index range" << endl; exit(0); } return arr2<ol> </ol> ; } int Getlen() { return len; } ~Array2D() { cout << "Array2" << endl; delete[]arr2; } }; int main() { Array2D arr(2, 2); for (int k = 0; k < 2; k++) { for (int p = 0; p < 2; p++) arr[k][p] = 1; } cout << arr[1][1] << endl; return 0; }
위에 있는 저 코드는 솔직이 무슨것을 하고자 하는지 혹은 어떤 구조로 정확히 돌아가는지 잘 모르겠습니다.
혹 도움을 주실분이 있으신지요..
Forums:
확인 방법은요
- 각 주소를 printf("%x", arr1)로 찍어봅니다.
- 생성자 소멸자에 출력순서를 확인해봅니다.
확인해보니. 생성 소멸 순서가. 좀 이상하네요.
생성자는 리턴값이 없는데. = 을 사용한것도 좀 걸립니다.
내용만으로 보면. 배열을 하나씩 생성해서 2차원 배열을 사용하려는 의도로 보입니다.
----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.
매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.
각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com
어설프게 작성되긴 했지만, [] 연산자 오버로딩을
어설프게 작성되긴 했지만, [] 연산자 오버로딩을 이용하여 2차원 배열을 흉내내는 예제로군요.
포인트는 main 함수의
Array2D arr(2,2)
가 마치int arr[2][2];
처럼 쓰이고 있다는 겁니다.1. Array1D와 Array2D의 내부 코드는 거의 같습니다. 타입이 다를 뿐이죠. Array1D는 int의, Array2D는 Array1D의 동적 할당된 배열을 가지고 있습니다.
2.
array[k][d]
를 보세요. 먼저array[k]
가Array2D::operator[]
함수를 부르고, 이 함수는 객체 내부의 배열에서 인덱스에 맞는 객체를 찾아Array1D&
타입으로 반환합니다. 그 다음[d]
가 달라붙어Array1D::operator[]
가 불리고, 마찬가지의 과정으로 적절한 객체가int&
타입으로 반환됩니다.3. 두
operator[]
함수들이 인덱스 범위 체크를 하고 있다는 점을 주목해보세요. C/C++의 raw array는 범위 체크를 하지 않죠.4. 소멸자에서 동적 할당된 배열을 삭제하고 있다는 점도 눈여겨볼 만 합니다.
답변 감사합니다.
답변 감사합니다. 분석결과 Arry1D 임시객체가 생성되고 직후에 바로 소멸되기 때문에
결국 같은 heap공간을 두번 메모리 해제하는 오류가 있네요.
원인은 생성자는 return되는 값이 없는데 arr2[i] = Array1D(n2); 여기에서 문제가 있는 듯 합니다.
그렇다면 operator=를 새로 정의 해주어야 한다는 것인데...
혹여 오류가 나지 않는 이 코딩에서 벗어나지 않는한에서 해결 된 코딩을 제가 받아볼 수 있을까요?
#include <iostream> #include
몇 가지 실수가 있어 덧붙입니다.
1. deep_copy 메서드는 public일 필요가 없고, 사실 여러 가지 측면에서 볼 때 private인 편이 훨씬 더 낫습니다.
2. 복사 생성자에서 꼭 이전에 할당한 메모리를 해제할 필요는 없을지도 모릅니다.
- 같은 크기의 배열을 대입할 땐 전에 할당해 놓은 메모리를 재사용할 수 있죠. (직접 그렇게 하도록 짜보세요.)
- 더 생각해보면, 더 작은 크기의 배열이 대입될 때에도 마찬가집니다. 이 경우 "할당한 동적 배열의 원래 크기"를 나타내는 필드가 하나 더 필요해지겠죠. 이 정도까지 하려면 코드가 약간 더 많이 바뀌어야 합니다.
3. 생각해보니 꼭 C++11까지 가지 않더라도 vector라는 좋은 컨테이너가 있네요.
맞습니다.
c++의 STL vector의 작동방식을 흉내내고자 한 코드인것 같습니다.
성의있는 답변 감사드립니다.
해보니 되네요.
----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.
매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.
각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com
이렇게 해보시기 바랍니다.
----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.
매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.
각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com
답변감사합니다.
어떤 컴파일러를 사용하시는지 모르겠으나, 근본적인 문제인 해제된 heap memory를 두번 해제하는것에 대해서는 근본적으로 해결이 안된듯 보입니다.
visual studio 2010에서는 동일한 오류가 생기네요.
다시 해보니. 틀렸네요.
메모리 해제는 정상적으로 보이는데요.
주소 값은 이상해보이네요.
DevC++ 로 확인해봤습니다.
이렇게 하니. 정확히 나옵니다.
----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.
매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.
각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com
에러가 난 이유는 이미 아셨으니... 해결책은 다른
에러가 난 이유는 이미 아셨으니... 해결책은 다른 분 댓글처럼 깊은 복사가 답일 수도 있겠습니다만,
어차피 Array1D 도 arr1 이 포인터로 구현되어서 arr1 이 가리키는 int 배열은 Array1D 객체와 별개의 위치에 저장되는 마당에,
굳이 Array2D 의 arr2 가 가리키는 공간을 Array1D 의 배열로 할 필요가 있나 싶은데요. 이걸 포인터의 배열로 하고 Array1D 객체들을 지역 변수가 생성되는 일 없이 처음부터 힙에 만들어버리시는 게 어떨런지.
고칠 부분만 원래 코드에 주석처리했습니다.
좋은 하루 되세요!
확인해보니. 됩니다.
----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.
매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.
각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com
Array1D 객체의 복사를 피할 수 있는 방법으로는
Array1D 객체의 복사를 피할 수 있는 방법으로는 이런 것도 있습니다.
raymundo님이 보여주신 방식과 위의 코드는 둘 다 Scott Meyers의 저서 More Effective C++ 중 항목 4에서 나오는 기법이죠. 그 항목에서 이 두 가지 방식 모두의 단점에 대해서도 설명하고 있으니 한 번 읽어보시길 권합니다.
어쨌거나, 이런 식으로 Array1D 객체의 복사를 피해간다고 해도 Array1D 객체가 현재 불완전한 구현이라는 건 변함이 없습니다. 깊은 복사를 해야 할 자리에 얕은 복사를 하는 기본 복사 생성자/대입 연산자가 있는 꼴이죠. 깊은 복사 코드를 짜 넣거나, 아니면 아예 복사를 불가능하게 막기라도 해야 합니다.
이거도 잘 되네요.
----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.
매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.
각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com
댓글 달기