: 객체의 복사본을 생성할때 호출되는 생성자이다.
: 이런식으로 컴파일러가 사용중이다.
왜냐하면 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의 멤버 변경 불가능하다.
1) 복사 생성자는 선언과 동시에 다른 오브젝트로 초기화를 할 경우에 해당된다.
대입연산자이지만, 선언과 동시에 초기화를 진행했으므로 이때는 복사 생성자가 호출된다.
선언과 동시에 초기화
2) 복사 대입연산자는 선언 및 초기화 후, 다른 객체로 대입을 할 경우에 발생한다.
1) private으로 옮기자.
2) public에 옮기고, delete 선언
: 복사 생성자가 호출되지 않는다... 무슨일일까?
컴파일러가 자동적으로 복사 생략을 한것이다.
복사를 했지만, Object(6)은 Rvalue이므로 컴파일러가 알아서 복사 생략을 진행한것이다.
디버그 모드일 때랑 릴리즈 모드일때 다르다.
-> 릴리즈 일때는 최적화가 이루어진다.
얕은 복사
: 동적할당된 포인터간의 복사가 이루어질때 발생하는 현상으로, 값복사가 아니라, 주소와 값까지 복사 대입하는 것.
- 특징으로는 2개의 포인터가 동일한 메모리를 가리키므로, 해제할 경우
동일한 메모리를 해제하므로 문제 발생한다.
깊은 복사
: 포인터 같의 복사가 이루어질때, 메모리가 아닌 값복사가 이루어지게 하는 복사의 형태
- 얕은복사를 방지하는 복사의 형태로, 2개의 포인터가 동일한 메모리를 가 리키는 것이 아니고, 서로 다른 메모리를 참조하는 형태이다.
-> 문제가 생기는 이유는 이미 해제된 메모리를 다시 해제하려고 해서 문제가 생긴 것이다.
-> 이런식으로 하면 깊은복사라고 할 수 있다!
정적할당된 변수의 경우, 문제가 없다.
동적할당된 변수의 경우에는 동일한 메모리를 해제하려고 해서 문제 발생!
해결코드
-> 복사생성자에서 새롭게 메모리를 할당하고, 매개인자로 받은 객체가 가리키는 곳의 value를 받도록 하자
: 복사 생성자와 동일하다. 이때는 동적할당은 하지않고, 참조되는 메모리의 value값만 받도록하자!