공부를 하는 입장이기 때문에, 내용에 오류가 있을 수 있습니다. 오류가 있다면 적극적으로 알려주시면 감사합니다!
class를 작성하면, 생성자나 소멸자처럼 우리가 작성하지 않으면 컴파일러가 자동으로 만들어주는 것이 더 있다. 대표적으로 복사 생성자와 대입 연산자가 있다.
복사 생성자 (copy constructor)
복사 생성자는 우리가 흔히 사용했는데, 객체를 다른 객체로 복사할 때 사용되는 특별한 생성자를 말한다. 기본적인 형태는 다음과 같이 생겼다.
ClassName (const ClassName & other) { }
객체 복사에 대한 2가지 방법의 예시가 있다.
#include <iostream>
class CopyableClass {
public:
int x = 0;
CopyableClass() {
std::cout << "생성자" << std::endl;
}
~CopyableClass() {
std::cout << "소멸자" << std::endl;
}
};
int main() {
CopyableClass obj1;
int x = 4;
CopyableClass obj2 = obj1; // 객체 복사
CopyableClass obj4(obj1); // 객체 복사
return 0;
}
당연하게 obj2와 obj4의 x의 값이 4라고 생각 되는데, 이는 복사 생성자를 내가 만들지 않아도 컴파일러가 복사 생성자를 만들어서 복사가 되었기 때문이다.
CopyableClass(const CopyableClass& other) {
x = other.x;
}
다음과 같이 컴파일러가 알아서 복사 생성자를 만들었고 복사할때 이 복사 생성자가 실행이 되었을 것이다. 따라서 obj2와 obj4의 x의 값이 4가 되는 것이다.
따라서 생성자나 소멸자 처럼 형식을 지킨다면 내가 직접 복사 생성자를 만들 수 있다.
복사 대입 연산자 (copy assignment operator)
복사 대입 연산자도 기능은 크게 다르지 않다. 말 그대로 대입할 때 사용되고, 이것도 컴파일러가 자동으로 만들어 준다. 기본 형태는 다음과 같다.
ClassName& operator=(const ClassName & other) { }
복사 대입의 예시로는 다음과 같다.
#include <iostream>
class CopyableClass {
public:
int x = 0;
CopyableClass() {
std::cout << "생성자" << std::endl;
}
~CopyableClass() {
std::cout << "소멸자" << std::endl;
}
};
int main() {
CopyableClass obj1;
int x = 4;
CopyableClass obj2;
obj2 = obj1;
return 0;
}
여기서도 컴파일러가 자동으로 복사 대입 연산자를 만들었고 대입이 진행이 됐을 때, 복사 대입 연산자가 실행이 되어 대입이 이루어졌다.
Delete, default
이처럼 컴파일러가 대입과 복사 생성자를 자동으로 만들게 되면 문제점이 프로젝트를 진행하다가 복사 혹은 대입을 해야 하면 안 되는 객체를 복사, 대입을 할 위험성이 생긴다. 따라서 delete를 이용하여 필요에 따라 제한해야 한다.
제한하는 방법은 매우 간단한데 위에서 말한 생성자들을 delete시키면 된다.
#include <iostream>
class NonCopyableClass {
public:
int x = 0;
NonCopyableClass() {
std::cout << "생성자" << std::endl;
}
// 복사 생성자와 복사 대입 연산자를 삭제하여 복사를 방지합니다.
NonCopyableClass(const NonCopyableClass&) = delete;
NonCopyableClass& operator=(const NonCopyableClass&) = delete;
~NonCopyableClass() {
std::cout << "소멸자" << std::endl;
}
};
int main() {
NonCopyableClass obj1; // 객체 생성은 가능합니다.
//NonCopyableClass obj2 = obj1; // 컴파일 에러: 복사 생성자가 삭제되었습니다.
// NonCopyableClass obj3;
// obj3 = obj1; // 컴파일 에러: 복사 대입 연산자가 삭제되었습니다.
return 0;
}
실제로 주석을 풀고 실행시키려고 하면 에러가 발생한다.
반대로 프로젝트에서 복사를 할수 있다는 것을 표시해주고 싶다면 default를 사용하면 된다.
'c++' 카테고리의 다른 글
[c++] visibility (0) | 2024.05.02 |
---|---|
[c++] __VA_ARGS__, parameter pack (0) | 2024.04.30 |
[c++] Range-based for loop (범위 기반 for 문) (1) | 2024.04.25 |
04. C++만의 특징 2 (0) | 2024.01.14 |
03. C언어 복습 (0) | 2024.01.04 |