class에서 대입연산자를 지정하지 않았을 경우?

lacovnk의 이미지

대입연산자를 지정하지 않으면 어떤 동작을 하게 되어 있나요?

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-

익명 사용자의 이미지

1. default assignment operator 로 넘어갑니다.
2. operator overloading에서 구현하는거나 copy 를 구현하는거나 같습니다.
3. 위와같이 클래스를 정의 할 경우 다음코드는 문제가 있습니다.

Image 
getThinnedImage(const Image& image) 
{ 
        Image result = image; 
        return result; 
}

4. effective c++을 보시기를 권해드립니다.

근데.. 글을 써놓고 다시 보니까 궁금한점이 생기네요..
copy constructor는 만들어주셨나요 ?

lacovnk의 이미지

Anonymous wrote:
1. default assignment operator 로 넘어갑니다.
2. operator overloading에서 구현하는거나 copy 를 구현하는거나 같습니다.
3. 위와같이 클래스를 정의 할 경우 다음코드는 문제가 있습니다.
Image 
getThinnedImage(const Image& image) 
{ 
        Image result = image; 
        return result; 
}

4. effective c++을 보시기를 권해드립니다.

근데.. 글을 써놓고 다시 보니까 궁금한점이 생기네요..
copy constructor는 만들어주셨나요 ?

1. copy constructor를 만들어주지 않았는데, 컴파일 에러가 나지 않았습니다 (-Wall -W) 그래서 기본 행동이 어떤지 궁금했던 건데.. 그 기본 assignment의 behavior가 어떻게 되나요?

2. 문제가 있다는 것은, 어떤 의미인지 설명해주실 수 있나요? (책은 집에 -o-;; ) 대입연산자나 대입에 의한 생성자를 만들어주지 않아서 그런건가요?

3. 그리고, copy를 구현하나 assign을 정의하나 마찬가지이겠지만, 혹시 관례가 있나 궁금해서요~ 예를 들면 assign은 불명확하므로 되도록 copy를 이용한다거나..

lifthrasiir의 이미지

lacovnk wrote:
대입연산자를 지정하지 않으면 어떤 동작을 하게 되어 있나요?

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-

1.
대입 연산자가 지정되지 않았을 경우 "기본 대입 연산자"가 지정됩니다. 이 기본 대입 연산자는 주어진 인스턴스 안의 멤버 변수들을 하나씩 자기 자신에게 대입합니다. 이런 동작은 복사 생성자도 똑같은데, 위의 경우 대입 연산자가 아니라 복사 생성자가 호출되겠지요. (Image result = image; 는 Image result(image); 와 같습니다) 예를 들어서 위의 경우 이런 식으로 정의되겠죠. (다른 변수가 있는 진 잘 모르겠으니 보이는 것만 씁니다)

Image::Image(const Image& other):
    width_(other.width_), height_(other.height_),
    pixel_array_(other.pixel_array_)
{}

동적으로 할당되는 포인터가 있다면 이러한 기본 대입 연산자와 복사 생성자는 위험합니다. 같은 주소를 두 번 delete하다 뻑날 수 있으니까요. 이상한 동작이 발생되는 것 같지 않더라도 포인터를 쓴다면 항상 대입 연산자와 복사 생성자도 구현하셔야 합니다.

2.
저 경우에는 그냥 연산자 오버로딩을 통해서 operator=를 구하는 게 가독성 면에서 나을 듯 합니다. 실질적으로 어느 걸로 하는 지는 취향 따라 결정하셔도 되겠지만...

3.
당장 보이는 걸로는... delete pixel_array_;가 아니라 delete[] pixel_array_; 되겠습니다. delete pixel_array_;라고만 하면 pixel_array_[0]만 해제됩니다.

- 토끼군

pool007의 이미지

Quote:

1. copy constructor를 만들어주지 않았는데, 컴파일 에러가 나지 않았습니다 (-Wall -W) 그래서 기본 행동이 어떤지 궁금했던 건데.. 그 기본 assignment의 behavior가 어떻게 되나요?

이것두 EC++, MEC++에 있지만..
assignment의 경우, member wise 로 operator=가
호출됩니다. 만약 멤버에 =가 정의되어있다면 그것이 불리고
정의가 되어있지 않다면 binary로 봐서 그대로 복사합니다.

Quote:

2. 문제가 있다는 것은, 어떤 의미인지 설명해주실 수 있나요? (책은 집에 -o-;; )

음 첫번째로 문제점은

Image 
getThinnedImage(const Image& image) 
{ 
        Image result = image; 
        return result; 
} 

여기에서 result = image가 되면서 result에 pixel_array_ 라는 포인터가 그대로 할당됩니다.
다음, return result에서 result는 복사되어 봔환되지만,
동시에 result라는 객체가 파괴됩니다. 이 시점에서
result의 pixel_array_가 delete되버립니다.
따라서

Image r = getThinnedImage(...)

를 호출하여 Image를 받은쪽에서 r.pixel_image_ 라는
변수는 이미 delete되어버린 상태가 됩니다. 즉, 값을
보장할 수 없죠..

Quote:

대입연산자나 대입에 의한 생성자를 만들어주지 않아서 그런건가요?

네.. 그것이 문제의 핵심입니다.

Quote:
3. 그리고, copy를 구현하나 assign을 정의하나 마찬가지이겠지만, 혹시 관례가 있나 궁금해서요~ 예를 들면 assign은 불명확하므로 되도록 copy를 이용한다거나..

EC++에서는 동적으로 메모리를 할당하는 경우 assignment와
copy constructor를 반드시 만들라고 되어있습니다. 그리고
하나만 만드는 것이 아니라, 둘다 같이 만들라고 권하고
있습니다.

--
Passion is like genius; a miracle.

lacovnk의 이미지

배운 내용들인데도 빼먹어버렸군요;;

지적들 감사합니다! ㅎㅎ 가서 EC++읽어봐야겠군요 -o-

원하는 동작 잘 하고 있습니다 ㅎㅎ

lacovnk의 이미지

Image 생성자에서, 사실 width_와 height_는 private입니다.

그런데

Image::Image(const Image& other):
    width_(other.width_), height_(other.height_)
{}

요 코드는 워닝조차 뿜지 않습니다;

이런 경우는, 같은 클래스라서 그런건가요? 음음.. 이것도 그 책에 보면 나오려나요? -o-

pool007의 이미지

lacovnk wrote:
Image 생성자에서, 사실 width_와 height_는 private입니다.

그런데

Image::Image(const Image& other):
    width_(other.width_), height_(other.height_)
{}

요 코드는 워닝조차 뿜지 않습니다;

이런 경우는, 같은 클래스라서 그런건가요? 음음.. 이것도 그 책에 보면 나오려나요? -o-

으음. 그거는 말씀하신대로 같은 클래스라서 그렇죠.

--
Passion is like genius; a miracle.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.