복사 생성자, 깊은 복사, 얕은복사

보물창고·2021년 8월 10일
0
post-thumbnail
  • 이것이 c++이다 - 4장 , 홍정모님의 따빼시 9.11절을 공부하고 정리한 내용입니다.

1. 복사 생성자란?

: 객체의 복사본을 생성할때 호출되는 생성자이다.

가) 형태

: 이런식으로 컴파일러가 사용중이다.
왜냐하면 const를 통해 다른 객체가 변경되는 것을 방지하고,
레퍼런스형 타입으로 복사본이 생기는 것을 방지하기 위함이다.

Object(const Object &other)
{

}

나) 주의할점

: 클래스 내부에서 동적할당 및 해제하는 멤버 포인터 변수를 관리할 경우 주의해야 한다.
-> 얕은 복사로 인해 이미 해제된 메모리를 참고하는 문제가 생긴다.

다) 언제 호출함?

1) 함수의 매개변수로 클래스를 사용할때
2) 🥺!!반환형으로 클래스를 사용할때!!
=> 이 때는 임시객체가 생성되는 문제 생긴다.

1) 매개변수로 클래스를 사용할때 예시

: Test함수를 통해 mNum을 7로 바꾸어주려고 햇는데 변경이 안됬다.
(이유)-> Test함수의 매개변수는 value 타입이어서 객체의 원본이 아닌 복사본의 mNum값을 변경한 것이다. 그러므로 외부에서의 값이 그대로이다.
(다른 문제) -> 복사 생성자가 호출되었다. Test의 매개변수가 객체여서 호출됨.

  • Call by Address나 Call by Reference로 변경하자.
    -> 복사 생성자가 호출되지는 않는다.
    - Call by Address의 경우는 포인터 하나의 크기가 증가한다.

    - Call by Ref는 메모리 크기 증대 되는 문제 없이 가능하다.

  • const를 매개변수에 붙이면 해당 obj의 멤버 변경 불가능하다.

2.복사 생성자와 복사 대입 연산자.

가) 복사 생성자와 복사 대입연산자가 호출되는 시점은 다르다!

1) 복사 생성자는 선언과 동시에 다른 오브젝트로 초기화를 할 경우에 해당된다.

  • 대입연산자이지만, 선언과 동시에 초기화를 진행했으므로 이때는 복사 생성자가 호출된다.

  • 선언과 동시에 초기화

2) 복사 대입연산자는 선언 및 초기화 후, 다른 객체로 대입을 할 경우에 발생한다.

나) copy 생성을 막자.

1) private으로 옮기자.

2) public에 옮기고, delete 선언

다) copy Elision : 복사 생략


: 복사 생성자가 호출되지 않는다... 무슨일일까?
컴파일러가 자동적으로 복사 생략을 한것이다.
복사를 했지만, Object(6)은 Rvalue이므로 컴파일러가 알아서 복사 생략을 진행한것이다.

라) 반환값 최적화

  • 디버그 모드일 때랑 릴리즈 모드일때 다르다.
    -> 릴리즈 일때는 최적화가 이루어진다.

    1. 디버그모드일 때

      : 지역변수를 반환해야하므로 복사가 이루어진 후, 반환함.
    1. 릴리즈 모드일때

      -> 컴파일러가 어차피 사라지는 값이므로 복사를 생략하고, 최적화로 그대로 반환시킴. 생명이 연장되는 것이다.
      Main 쪽의 result 객체는 doSomething의 a객체가 되어버린 것이다!

3. 깊은 복사와 얕은 복사

  • 얕은 복사
    : 동적할당된 포인터간의 복사가 이루어질때 발생하는 현상으로, 값복사가 아니라, 주소와 값까지 복사 대입하는 것.
    - 특징으로는 2개의 포인터가 동일한 메모리를 가리키므로, 해제할 경우
    동일한 메모리를 해제하므로 문제 발생한다.

  • 깊은 복사
    : 포인터 같의 복사가 이루어질때, 메모리가 아닌 값복사가 이루어지게 하는 복사의 형태
    - 얕은복사를 방지하는 복사의 형태로, 2개의 포인터가 동일한 메모리를 가 리키는 것이 아니고, 서로 다른 메모리를 참조하는 형태이다.

가)얕은 복사 예시


-> 문제가 생기는 이유는 이미 해제된 메모리를 다시 해제하려고 해서 문제가 생긴 것이다.

  • 해결방법으로는 가리키는 곳의 값만 복사되도록 변경해야 한다.

    -> 포인터이므로 포인터의 메모리는 확보해야 한다!


-> 이런식으로 하면 깊은복사라고 할 수 있다!

나) 클래스에서의 얕은 복사와 깊은 복사.

복사 생성자.

  • 정적할당된 변수의 경우, 문제가 없다.

  • 동적할당된 변수의 경우에는 동일한 메모리를 해제하려고 해서 문제 발생!

  • 해결코드

    -> 복사생성자에서 새롭게 메모리를 할당하고, 매개인자로 받은 객체가 가리키는 곳의 value를 받도록 하자

복사 대입연산자.

: 복사 생성자와 동일하다. 이때는 동적할당은 하지않고, 참조되는 메모리의 value값만 받도록하자!

profile
🔥🔥🔥

0개의 댓글