-
[C++] 대입연산자프로그래밍/C & C++ 2024. 7. 8. 00:05728x90반응형
대입 연산자(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
라는 포인터 멤버를 깊은 복사하여 대입 연산자를 정의합니다.delete
와new
를 사용하여 기존 리소스를 해제하고 새로운 메모리를 할당하여 복사합니다.이동 대입 연산자 (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