• 카테고리

    질문 & 답변
  • 세부 분야

    프로그래밍 언어

  • 해결 여부

    미해결

대입 연산자 오버로딩 연습문제 질문

23.08.14 20:17 작성 23.08.14 20:35 수정 조회수 224

1

IntArray& operator = (const IntArray& source)
{
    if (this == &source)
        return *this;
    
    delete[] m_data; 

    m_length = source.m_length;

    if (source.m_data != nullptr)
    {
        m_data = new int[m_length];

        for (int i = 0; i < m_length; ++i)
            m_data[i] = source.m_data[i];
    }
    else
        m_data = nullptr;

    return *this;
} 


IntArray& operator = (const std::initializer_list<int>& list)
{
    // 어차피 IntArray와 Initializer_list는 다른 자료형이므로 같은 메모리를 공유하고 있지 않을 것이기 때문에 self-assignment 방지는 필요 없지 않을까?

    delete[] m_data; 

    m_length = list.size();
    m_data = new int[m_length];

    int count = 0;
    for (auto & element : list)
    {
        m_data[count] = element;
        ++count;
    } 

    return *this;
}


int main()
{
/* case 1) assignment operator 양 쪽 모두 IntArray인 경우 */
    IntArray array1 {1, 2, 3};
    IntArray array2 {4, 5, 7};
    array1 = array2;

    cout << array1 << endl;

/* case 2) assignment operator 오른쪽에 initializer list가 오는 경우 */
    IntArray array3 {1, 2, 3}; 
    array3 = {4, 5, 7};

    cout << array3 << endl;

    return 0;
} 

수업 중 나온 연습문제에 대해 두 가지 방식으로 구현을 해보았습니다. operator overloading을 할 때 IntArray를 parameter로 받을 수도 있고, initializer_list를 parameter로 받을 수도 있다고 생각했기 때문입니다.

두 가지 operator overloading을 각각 따로 구현해보았을 때,
(1) IntArray& operator = (const IntArray& source); 의 경우 main 함수에 있는 두 가지 경우가 모두 정상적으로 실행되는 반면,
(2) IntArray& operator = (const std::initializer_list<int>& list);의 경우 case2)만 에러 없이 정상적으로 실행되었습니다. (case 1)에서 cout으로 확인해보면, 대입은 정상적으로 이루어졌으나 에러는 아래와 같은 에러메시지가 뜹니다!)

operator overloading 시 parameter를 IntArray로 받는 (1)의 경우, 대입 연산자 우측에 initializer list가 있는 case2에서는 실행이 되면 안될 것 같은데 에러메시지 없이 대입가능한 이유가 궁금합니다!

답변 2

·

답변을 작성해보세요.

2

Soobak님의 프로필

Soobak

2023.08.15

안녕하세요, 답변 도우미 Soobak 입니다.

이미 답변을 달아주신 NE 님께서 정확하게 설명해주셨습니다. !!! 🙏

마지막으로 질문해주신 "operator overloading 시 parameter를 IntArray로 받는 (1)의 경우, 대입 연산자 우측에 initializer list가 있는 case2에서는 실행이 되면 안될 것 같은데 에러메시지 없이 대입가능한 이유가 궁금합니다!" 에 대해서도 NE 님께서 정확하게 설명해주셨습니다.
array3 = {4, 5, 7}; 형태의 대입에서 operator = 을 통해 대입이 가능한 이유는 암묵적인 변환 때문입니다.

좋은 질문을 해주신 질문자님과, 좋은 답변을 해주신 NE 님 모두 감사드립니다.

감사합니다! 그렇다면 혹시 위 연습문제에서 연산자 오버로딩을 할 경우, parameter를 IntArray, initializer list로 받는 두 경우 모두 재정의해주어야 모든 경우에서 제대로 작동한다고 볼 수 있나요?

Soobak님의 프로필

Soobak

2023.08.15

안녕하세요, 답변 도우미 Soobak 입니다.

네, 그렇습니다.
array1 = array2; 와 같이 일반적인 객체 대입에 대한 IntArray 매개변수에 대한 오버로딩과, array3 = {4, 5, 7}; 과 같이 Initializer List 를 사용하여 객체를 초기화하는 경우,
두 가지 경우 모두에 대해서 명시적으로 오버로딩을 해주어야 일시적인 객체 생성(암묵적 변환)없이도 Initiallizer List 를 직접 처리할 수 있습니다.

1

NE님의 프로필

NE

2023.08.14

Double Free 에러가 발생하는 이유는 operator = (const std::initializer_list<int>& list) 연산자로
처리되는 것이 아닌 얕은 복사로 처리되었기 때문에 Double Free 에러가 발생하는 것 같습니다.

(operator= 연산자 재정의 본문에 std::cout << "operator= called" << std::endl 구문을 추가해보시면,
호출되지 않음을 직접 확인해보실 수 있을 것 같습니다.)


operator = (const IntArray& source) 재정의만 했음에도,
array3 = {4, 5, 7} 구문이 실행되는 이유는 암시적으로 생성자가 호출되었기 때문인 것 같습니다.
(생성자 본문에 std::cout << "Constructor called" << std::endl; 구문을 추가해보시면,
직접 확인이 가능하실 것 같습니다.)

정말 감사합니다!!!