ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [C++] 대입연산자
    프로그래밍/C & C++ 2024. 7. 8. 00:05
    728x90
    반응형

    대입 연산자(Assignment Operator)는 C++에서 객체를 다른 객체로 복사하거나 값을 할당할 때 사용됩니다. 기본 대입 연산자 외에도 사용자 정의 대입 연산자를 정의하여 클래스 멤버의 복사나 할당 방식을 제어할 수 있습니다. 이 작업은 특히 동적 메모리를 사용하는 클래스에서 중요한 역할을 합니다.

    기본 대입 연산자

    C++에서는 컴파일러가 기본적으로 제공하는 대입 연산자가 있습니다. 이는 클래스의 멤버 변수를 하나씩 복사하는 "얕은 복사"를 수행합니다. 하지만, 동적 메모리나 리소스를 관리하는 경우, 기본 대입 연산자는 올바르게 동작하지 않을 수 있습니다.

    #include <iostream>
    
    class MyClass {
    public:
        int value;
    };
    
    int main() {
        MyClass obj1;
        obj1.value = 5;
    
        MyClass obj2;
        obj2 = obj1; // 기본 대입 연산자 호출
    
        std::cout << "obj2.value: " << obj2.value << std::endl; // 출력: 5
    
        return 0;
    }

    사용자 정의 대입 연산자

    사용자 정의 대입 연산자를 통해 클래스의 멤버 변수를 올바르게 복사하거나 할당할 수 있습니다. 사용자 정의 대입 연산자를 정의할 때는 다음 사항을 고려해야 합니다:

    • 자기 대입 방지: 객체 자신에 대한 대입을 처리합니다.
    • 기존 리소스 해제: 대입 전에 기존 리소스를 적절히 해제합니다.
    • 깊은 복사: 필요한 경우 멤버 변수를 깊은 복사합니다.

    예제: 깊은 복사를 위한 대입 연산자

    #include <iostream>
    
    class MyClass {
    private:
        int* data;
    
    public:
        // 생성자
        MyClass(int value) : data(new int(value)) {}
    
        // 소멸자
        ~MyClass() { delete data; }
    
        // 복사 생성자
        MyClass(const MyClass& other) : data(new int(*other.data)) {}
    
        // 대입 연산자
        MyClass& operator=(const MyClass& other) {
            if (this == &other) {
                return *this; // 자기 대입 방지
            }
    
            delete data; // 기존 리소스 해제
            data = new int(*other.data); // 깊은 복사
    
            return *this;
        }
    
        // 출력 메서드
        void print() const { std::cout << "Value: " << *data << std::endl; }
    };
    
    int main() {
        MyClass obj1(10);
        MyClass obj2(20);
    
        obj2 = obj1; // 사용자 정의 대입 연산자 호출
    
        obj1.print(); // 출력: Value: 10
        obj2.print(); // 출력: Value: 10
    
        return 0;
    }

    위 예제에서는 data라는 포인터 멤버를 깊은 복사하여 대입 연산자를 정의합니다. deletenew를 사용하여 기존 리소스를 해제하고 새로운 메모리를 할당하여 복사합니다.

    이동 대입 연산자 (Move Assignment Operator)

    C++11에서는 이동 의미론을 도입하여 리소스를 효율적으로 이동할 수 있습니다. 이동 대입 연산자는 객체의 소유권을 이동하며, 불필요한 복사를 피합니다.

    #include <iostream>
    #include <utility> // std::move
    
    class MyClass {
    private:
        int* data;
    
    public:
        // 생성자
        MyClass(int value) : data(new int(value)) {}
    
        // 소멸자
        ~MyClass() { delete data; }
    
        // 복사 생성자
        MyClass(const MyClass& other) : data(new int(*other.data)) {}
    
        // 복사 대입 연산자
        MyClass& operator=(const MyClass& other) {
            if (this == &other) {
                return *this; // 자기 대입 방지
            }
    
            delete data; // 기존 리소스 해제
            data = new int(*other.data); // 깊은 복사
    
            return *this;
        }
    
        // 이동 생성자
        MyClass(MyClass&& other) noexcept : data(other.data) {
            other.data = nullptr; // 이동 후 원본 객체의 포인터를 nullptr로 설정
        }
    
        // 이동 대입 연산자
        MyClass& operator=(MyClass&& other) noexcept {
            if (this == &other) {
                return *this; // 자기 대입 방지
            }
    
            delete data; // 기존 리소스 해제
            data = other.data; // 리소스 이동
            other.data = nullptr; // 이동 후 원본 객체의 포인터를 nullptr로 설정
    
            return *this;
        }
    
        // 출력 메서드
        void print() const { 
            if (data) {
                std::cout << "Value: " << *data << std::endl; 
            } else {
                std::cout << "No value" << std::endl;
            }
        }
    };
    
    int main() {
        MyClass obj1(10);
        MyClass obj2(20);
    
        obj2 = std::move(obj1); // 이동 대입 연산자 호출
    
        obj1.print(); // 출력: No value
        obj2.print(); // 출력: Value: 10
    
        return 0;
    }

    위 예제에서 이동 대입 연산자를 정의하여 객체의 소유권을 효율적으로 이동합니다. std::move를 사용하여 obj1의 데이터를 obj2로 이동하고, obj1은 더 이상 유효한 데이터를 가지지 않습니다.

    결론

    • 기본 대입 연산자: 컴파일러가 제공하는 대입 연산자로, 멤버 변수를 얕은 복사합니다.
    • 사용자 정의 대입 연산자: 클래스의 멤버 변수를 올바르게 복사하거나 할당하기 위해 정의합니다.
    • 이동 대입 연산자: 리소스를 효율적으로 이동하기 위해 정의하며, C++11부터 사용 가능합니다.

    이러한 연산자들을 올바르게 정의함으로써, 클래스의 복사, 할당, 이동 동작을 제어할 수 있으며, 메모리 누수와 같은 문제를 방지할 수 있습니다.

    728x90
    반응형

    '프로그래밍 > C & C++' 카테고리의 다른 글

    [C++] 연산자 다중 정의 (Operator Overloading)  (0) 2024.07.08
    [C++] Explicit  (0) 2024.07.08
    [C++] 댕글링 포인터 (Dangling Pointer)  (0) 2024.07.07
    [C++] 클래스 생성자 맴버 초기화  (0) 2024.07.07
    [C++] Delete  (0) 2024.07.07
Designed by Tistory.