항목 5: C++가 은근슬쩍 만들어 호출해 버리는 함수들에 촉각을 세우자
빈 클래스라도 컴파일러가 자동으로 생성해주는 멤버함수
- 복사생성자 외 생성자 선언 안했을 경우
- 기본 생성자
- 따로 정의하지 않은 경우
- 복사 생성자
- 복사 대입 연산자
복사는 데이터 사본을 그대로 복사함 (얕은 복사) - 소멸자
==> 컴파일러가 자동 생성하는 함수가 있음을 인지하고 직접 선언하여 명확히 처리하자
class CClass
{
private:
char* name;
public:
//기본 생성자
CClass() {}
//복사 생성자 (동적할당 얕은 복사 주의)
CClass(const CClass &class) {}
//복사 대입 연산자 (동적할당 얕은 복사 주의)
CClass& operator=(const Class &class) {}
}
int main()
{
CClass class; //기본
CClass copy(class); //복사
CClass temp = class; //복사, 생성 때 같은 타입을 대입 연산하면 복사 생성자 호출함
class = copy; //대입, 이미 생성되어 있는 객체에 값 복사할 때 사용됨
}
해당 내용은 C++98까지 이고 C++11에서는 자동 생성되는 함수들이 추가 되었다
- 이동 생성자
- 이동 대입 연산자
==> 성능이랑 불필요한 복사를 최소화해주기 때문에 미리 알아두는게 좋다.
얕은 복사?
포인트 변수는 주솟값을 담을 수 있는 변수로 복사생성자를 따로 정의하지 않으면 주소값만 복사가 됨
--> 동일한 주소를 가리키는 인스턴스가 생기게 된다
--> 주소값만 복사했을 경우 해당 주소가 해제되어도 포인터는 그대로 해당 주소를 가리키고 있다.
(메모리가 해제된 곳을 가리키고 있는 포인터를 dangling pointer라 함)
=> 이걸 막기 위해서 shared_ptr 같은 별도의 매니저 단의 클래스를 사용한다 (or memcopy 같은 걸 써서 직접 복사해야함)
class Person{
int age;
char* name;
Person(int _age, const char* _name)
{
age = _age;
name = new char[strlen(_name) + 1];
strcpy(name, _name);
}
//복사생성자; 깊은 복사
Person(const Person& person)
{
age = person.age;
name = new char[strlen(person.name) + 1];
strcpy(name, person.name)
}
}
항목 6: 컴파일러가 만들어낸 함수가 필요 없으면 확실히 이들의 사용을 금해 버리자
컴파일러가 자동으로 생성하는 public 멤버함수가 불필요한 경우, 링크/컴파일 에러를 발생시켜 확실하게 막자
ex) 세상에 똑같은 자동차가 두 개 존재할 수 없음 / 동일한 집 매물이 두 개 존재할 수 없음 --> 복사 생성자 막기
컴파일러가 자동 생성하는 복사 관련 함수 막는 방법
- 링크 단계 방법: private으로 복사생성자/복사대입연산자 선언 후 정의하지 않기
- 컴파일 단계 방법: 복사 관련 함수가 private으로 선언된 클래스를 만들어 상속받기
class CUncopyable
{
public:
private:
//정의 X --> 내부 호출 시 undefined 링크 에러
//선언에서는 매개변수 이름도 필요 없음 (type과 identifirer만 컴파일러에게 알려주는 것이기 때문)
CUncopyable(const CUncopyable&);
CUncopyable& opertator=(const CUncopyable&);
};
//public/protected/private이든 derived class의 멤버들은 base class의 private 멤버에 접근 자체가 불가능함 --> 컴파일 에러 발생
class CTemp : private CUncopyable
{
public:
//CTemp의 멤버함수나 friend 함수에서 copy를 하려고 하면 CTemp에는 복사 관련 함수가 없으니 생성하려 할텐데
//이때 컴파일러는 base class의 대응 버전을 호출하게 되어있음
}
클래스를 private으로 상속받는 케이스는 잘 없다
private / public / protected 를 정확히 지켜주며 개발해야 함
'Programming > C++' 카테고리의 다른 글
작성중) 자료형과 타입 캐스팅 (0) | 2022.06.23 |
---|---|
[Effective C++] Chapter 2. 생성자, 소멸자 및 대입 연산자(2) (0) | 2022.06.12 |
[Visual Studio 2017] 단축키 모음 (0) | 2022.02.27 |
.a와 .so 라이브러리 (Dependency) (0) | 2022.02.26 |
[Effective C++] Chapter 1. C++에 왔으면 C++의 법을 따릅시다. (2) | 2022.02.15 |