[Effective C++] 항목 5 : C++가 은근슬쩍 만들어 호출해 버리는 함수들에 촉각을 세우자

수민이슈·2023년 3월 15일
0

Effective C++

목록 보기
5/30
post-thumbnail

스콧 마이어스의 Effective C++을 읽고 개인 공부 목적으로 요약 작성한 글입니다!

💡 컴파일러는 경우에 따라 클래스에 대해 기본 생성자, 복사 생성자, 복사 대입 연산자, 소멸자를 암시적으로 만들어 놓을 수 있다!

🖊️ 생성자, 소멸자, 대입 연산자

생성자

: 새로운 객체를 메모리에 만드는데 필요한 과정을 제어하고, 객체의 초기화를 맡는 함수

소멸자

: 객체를 없앰 + 그 객체가 메모리에서 적절히 사라질 수 있도록 하는 과정을 제어하는 함수

대입 연산자

: 기존의 객체에 다른 객체의 값을 줄 때 사용하는 함수


🖊️ 컴파일러가 저절로 선언해주는 멤버함수

class Empty{};

만약 내가 위에 코드처럼 클래스를 선언했다면,
아래 코드에 있는 것들을 만든다고 봐도 된다.
컴파일러가 필요하다고 생각하면 걍 만들어준다.

class Empty {
public:
	Empty() { ... } 									// 기본 생성자
    Empty(const Empty& rhs) { ... } 					// 복사 생성자
    ~Empty() { ... } 									// 소멸자
    
    Empty& operator= (const Empty& rhs) { ... } 		// 복사 대입 연산자

언제 필요한데?

Empty e1;					// 기본 생성자, 소멸자 필요

Empty e2(e1);				// 복사 생성자 필요
e2 = e1;					// 복사 대입 연산자 필요

특징은?

기본 생성자 (Default Constructor)

컴파일러는 사용자가 생성자를 선언해놓지 않으면, 기본 생성자를 선언해놓는다.
(Public, inline)

생성자를 선언해놓았다면 컴파일러는 기본 생성자를 생성하지 않는다.

복사 생성자 (Copy Constructor)

원본 객체의 비정적 데이터를 사본 객체 쪽으로 복사해준다.

복사 대입 연산자 (Copy Assignment Operator)

복사 생성자가 하는 일과 거의 비슷하긴 함
최종 결과 코드가 '적법해야'하고, '이치에 닿아야만'한다.
안그러면 컴파일러는 operator=의 자동 생성을 해주지 않고, 직접 정의해줘야 함.

소멸자 (Destructor)

소멸자는 클래스가 상속한 기본 클래스의 소멸자가 가상 소멸자로 되어 있지 않으면
역시 비가상 소멸자로 만들어진다.


🖊️ 복사 대입 연산자를 직접 정의해줘야 하는 경우

예시 : 참조자를 데이터 멤버로 가지는 경우

template<class T>
class NameObject {
public:
	NameObject(string& name, const T& value);
    
    ...
    
private:
	string& nameValue;
    const T objectValue;
};


string newDog("Persephone");
string oldDog("Satch");

NameObject<int> p(newDog, 2);
NameObject<int> s(oldDog, 26);

p = s;

이런 경우,,

nameValue는 string에 대한 참조자 이고, objectValue는 상수이다.
p = s; 을 실행할 때, p에 들어있는 데이터 멤버는 어떻게 될까유?

어떻게 하면 좋을까?

C++의 참조자는 원래 자신이 참조하고 있는 것과 다른 객체를 참조할 수 없다.
그래서 참조자 자체는 바뀔 수 없다

p.nameValue가 참조하는 string 객체 자체가 바뀐다면, 실제 대입 연산에 직접적으로 관여하지 않는 객체도 영향을 받는다.

결국 컴파일 에러가 난다.

결국, 직접 정의해줘야 한다.


😊느낀점

정말 기본 of 기본이지만,,!!
생성자 관련 부분은 넘 중요하고 꼭 알아야 하는 것 같다.

0개의 댓글