class에서 대입연산자를 지정하지 않았을 경우?
글쓴이: lacovnk / 작성시간: 토, 2005/10/22 - 11:25오전
대입연산자를 지정하지 않으면 어떤 동작을 하게 되어 있나요?
Image image = blabla.. Image timage = getThinnedImage(image);
위와 같은 작업을 합니다.
참고로 Image의 생성자와 소멸자는 다음과 같습니다.
Image::Image(unsigned int width,unsigned int height,Pixel pixel): width_(width),height_(height) { pixel_array_ = new Pixel*[width]; for(unsigned int i=0;i<width;i++){pixel_array_[i] = new Pixel[height];} for(unsigned int y=0;y<height;y++) { for(unsigned int x=0;x<width;x++){setPixel(x,y,pixel);} } } Image::~Image() { cout << "Delete Image "; for(unsigned int x=0;x<width_;x++){cout << x << " ";cout.flush();delete[] pixel_array_[x];} delete pixel_array_; }
Image getThinnedImage(const Image& image) { Image result = image; return result; }
위와 같이 했더니.. ~Image()가 두번 불리는데, 두번째에서 ~Image에서 멈춰버립니다. (0을 출력하고 멈춥니다)
Image getThinnedImage(const Image& image) { Image result(image.getWidth(),image.getHeight(),Pixel(255,255,255)); return result; }
이렇게 하면 두번의 소멸자가 정상적으로 종료됩니다.
만약 포인터만 가져갔다면, 두번째 delete에서 세폴이 나야 할 것 같은데.. debug해보면, 0번째 줄에서 계속 도는 것 같습니다. (충분히 돌려보진 않았습니다만 -o-)
1. class에서 대입 연산자를 지정하지 않을 경우, 어떤 행동을 보이나요?
2. .copy()를 해주는게 나을까요, 아니면 = 연산자 오버로딩을 하는게 나을까요?아니면 둘다? 어떤 상황이 있는지 궁금합니다.
3. 위의 코드에 문제는 없나요? -o-
Forums:
1. default assignment operator 로 넘어갑니다.
1. default assignment operator 로 넘어갑니다.
2. operator overloading에서 구현하는거나 copy 를 구현하는거나 같습니다.
3. 위와같이 클래스를 정의 할 경우 다음코드는 문제가 있습니다.
4. effective c++을 보시기를 권해드립니다.
근데.. 글을 써놓고 다시 보니까 궁금한점이 생기네요..
copy constructor는 만들어주셨나요 ?
[quote="Anonymous"]1. default assignment
1. copy constructor를 만들어주지 않았는데, 컴파일 에러가 나지 않았습니다 (-Wall -W) 그래서 기본 행동이 어떤지 궁금했던 건데.. 그 기본 assignment의 behavior가 어떻게 되나요?
2. 문제가 있다는 것은, 어떤 의미인지 설명해주실 수 있나요? (책은 집에 -o-;; ) 대입연산자나 대입에 의한 생성자를 만들어주지 않아서 그런건가요?
3. 그리고, copy를 구현하나 assign을 정의하나 마찬가지이겠지만, 혹시 관례가 있나 궁금해서요~ 예를 들면 assign은 불명확하므로 되도록 copy를 이용한다거나..
Re: class에서 대입연산자를 지정하지 않았을 경우?
1.
대입 연산자가 지정되지 않았을 경우 "기본 대입 연산자"가 지정됩니다. 이 기본 대입 연산자는 주어진 인스턴스 안의 멤버 변수들을 하나씩 자기 자신에게 대입합니다. 이런 동작은 복사 생성자도 똑같은데, 위의 경우 대입 연산자가 아니라 복사 생성자가 호출되겠지요. (Image result = image; 는 Image result(image); 와 같습니다) 예를 들어서 위의 경우 이런 식으로 정의되겠죠. (다른 변수가 있는 진 잘 모르겠으니 보이는 것만 씁니다)
동적으로 할당되는 포인터가 있다면 이러한 기본 대입 연산자와 복사 생성자는 위험합니다. 같은 주소를 두 번 delete하다 뻑날 수 있으니까요. 이상한 동작이 발생되는 것 같지 않더라도 포인터를 쓴다면 항상 대입 연산자와 복사 생성자도 구현하셔야 합니다.
2.
저 경우에는 그냥 연산자 오버로딩을 통해서 operator=를 구하는 게 가독성 면에서 나을 듯 합니다. 실질적으로 어느 걸로 하는 지는 취향 따라 결정하셔도 되겠지만...
3.
당장 보이는 걸로는... delete pixel_array_;가 아니라 delete[] pixel_array_; 되겠습니다. delete pixel_array_;라고만 하면 pixel_array_[0]만 해제됩니다.
- 토끼군
[quote]1. copy constructor를 만들어주지 않았는데
이것두 EC++, MEC++에 있지만..
assignment의 경우, member wise 로 operator=가
호출됩니다. 만약 멤버에 =가 정의되어있다면 그것이 불리고
정의가 되어있지 않다면 binary로 봐서 그대로 복사합니다.
음 첫번째로 문제점은
여기에서 result = image가 되면서 result에 pixel_array_ 라는 포인터가 그대로 할당됩니다.
다음, return result에서 result는 복사되어 봔환되지만,
동시에 result라는 객체가 파괴됩니다. 이 시점에서
result의 pixel_array_가 delete되버립니다.
따라서
를 호출하여 Image를 받은쪽에서 r.pixel_image_ 라는
변수는 이미 delete되어버린 상태가 됩니다. 즉, 값을
보장할 수 없죠..
네.. 그것이 문제의 핵심입니다.
EC++에서는 동적으로 메모리를 할당하는 경우 assignment와
copy constructor를 반드시 만들라고 되어있습니다. 그리고
하나만 만드는 것이 아니라, 둘다 같이 만들라고 권하고
있습니다.
--
Passion is like genius; a miracle.
앗 이런 실수를 -o-
배운 내용들인데도 빼먹어버렸군요;;
지적들 감사합니다! ㅎㅎ 가서 EC++읽어봐야겠군요 -o-
원하는 동작 잘 하고 있습니다 ㅎㅎ
앗 덧붙여..
Image 생성자에서, 사실 width_와 height_는 private입니다.
그런데
요 코드는 워닝조차 뿜지 않습니다;
이런 경우는, 같은 클래스라서 그런건가요? 음음.. 이것도 그 책에 보면 나오려나요? -o-
Re: 앗 덧붙여..
으음. 그거는 말씀하신대로 같은 클래스라서 그렇죠.
--
Passion is like genius; a miracle.
댓글 달기