const 멤버함수, const 객체
데이터멤버의 값이 변하지않는 멤버함수에 대해서는 const키워드를 지정해줄 수 있다. (안해줘도 문제는 없지만 문제가되는경우가 있음)
int getValue() const { return value; }에서 **const**는 멤버 함수가 해당 객체의 멤버 변수들을 수정하지 않도록 보장하는 역할을 합니다. 이 const 한정자는 함수 선언의 끝에 위치하며, 이 함수가 객체의 상태를 변경하지 않는다는 것을 의미합니다.
상수 객체의 의미
const Counter c;에서의 **const**는 객체 c가 상수 객체임을 나타냅니다. 즉, 객체 c의 상태를 변경할 수 없도록 보장합니다.
- const 객체는 선언된 후 멤버 변수 값을 변경할 수 없습니다. 따라서, 모든 멤버 함수 중 const 멤버 함수만 호출할 수 있습니다.
- c가 상수 객체이므로, c를 통해 멤버 변수 값을 변경하는 비-const 멤버 함수는 호출할 수 없습니다.
- 컴파일러는 값을 바꾸느냐를 확인하는게 아니라 const가 지정되어있느냐 안되어있느냐만 확인함
const Counter& c 를 쓰려면 int getValue()에 const를 꼭 붙여줘야 에러가 나지 않는다.
생성자
Person::Person() ==> person 클래스의 멤버인 생성자 Person이라는뜻
this 는 객체 자기자신을 뜻함
this->name 하면 데이터멤버 name을 뜻함
소멸자
-소멸자의 머리에 반환자료형을 표시하지않으며 return명령으로 값을 반환할 수 없음
-매개변수가 없으며 클래스에 하나의 소멸자만 정의할 수있음.
-public으로 선언하는 것이 반적
-상속을 통해 파생클래스를 정의하는 경우 virtual을 지정하여 가상함수가 되도록하는 것이 좋음
디폴트 생성자
-매개변수가 없는 생성자 또는 모든 매개변수에 디폴트 인수가 지정된 생성자
-클래스를 선언할때 생성자를 선언하지 않으면 컴파일러는 묵시적으로 디폴트 생성자를 정의함
- 생성자를 하나라도 선언하면 컴파일러는 묵시적 디폴트 생성자를 정의하지 않음.
복사생성자
묵시적 복사 생성자
객체를 인수로 받는 생성자는 만들지않았지만 컴파일러가 묵시적으로 복사생성자가 있다고 가정하기떄문에 cnt4를 인수로 받을 수 있다.
CounterM cnt6=cnt4; 는 대입명령이 아니라 cnt6{cnt4} 와 같다.
rvalue참조
10은 상수 자체 . 이름이없음 이는 rvalue임
함수의 리턴값은 리턴값의 위치를 참조할 방법이 없으니까(값을 전달하고나면 없어질거니까) rvalue
v2는 identity가 있는 lvalue임
이동생성자
rvalue참조로 전달된 같은 클래스의 객체의 내용을 이동하여 객체를 만드는 생성자
복사생성자의 경우는 const 를 넣는데 (원본 객체를 보존하니까)
이동생성자는 const를 뺀다.( 생성되는 객체에 자원을 옮기는 거니까)
파란글씨가 이동생성자이다 fv에 있는 자원을 그대로 가져옴(이동)
가리키고 있던 메모리는 새로생성되는 객체에 전달이 되었고
fv.arr=nullptr;로
fv.n=0;
이동 생성자의 목적은 소유권을 이전하는 것이기 때문에, 원본 객체의 자원을 새로운 객체로 "이동"시키고, 원본 객체는 더 이상 자원을 소유하지 않도록 설정해야 합니다. 만약 이동 후 원본 객체가 여전히 자원을 가리키고 있으면 이중 해제(double free) 오류가 발생할 수 있습니다.
- 이동 생성자의 역할:
- 이동 생성자는 객체의 자원을 새 객체로 이전합니다. 이때 원본 객체는 자원을 더 이상 소유하지 않는 상태로 만들어야 합니다.
- 원본 객체의 자원이 nullptr로 설정되지 않으면, 원본 객체가 여전히 그 자원을 가리키고 있는 상태가 됩니다.
- 이중 해제 오류:
- 이동된 후 원본 객체가 소멸되면, 원본 객체의 소멸자가 자원을 해제하려고 시도할 것입니다.
- 하지만 이동된 객체도 소멸될 때 같은 자원을 해제하려고 합니다.
- 결과적으로 같은 자원을 두 번 해제하려는 시도로 인해 프로그램이 충돌할 수 있습니다
v1.add(v2)는 rvalue이기때문에 rvalue에 해당하는 이동생성자(파란글씨) 가 호출이된다.
이동된 후에는
이렇게 된다.
static
static 데이터멤버는 클래스선언문안에서 선언만해줌
정의는 별도로 있어야함 프로그램내에서 1번만 있어야하기때문에
헤더파일에있으면 여러소스파일에 include되면서 똑같은 대상이 여러번 정의되는 문제가발생해서 충돌발생함
객체가 만들어지지않아도 "클래스이름::스태틱멤버함수이름" 을 통해서 스태틱멤버함수를 실행시킨다
NamedObj::nObj()
1번 Copycat(Copycat cc) (잘못된 선택)
- 문제점: Copycat cc와 같이 객체를 값으로 복사하는 방식으로 매개변수를 전달하면, 복사 생성자 호출 시 다시 복사 생성자를 호출하게 됩니다. 이로 인해 무한 재귀 호출이 발생하며, 프로그램이 제대로 동작하지 않고 스택 오버플로우 오류가 발생할 수 있습니다.
- 이유: 복사 생성자는 원래 기존 객체를 새로운 객체에 복사할 때 호출되므로, 매개변수로 값이 아닌 참조를 받아야 합니다.
2번 Copycat(const Copycat cc) (잘못된 선택)
- 문제점: const Copycat cc와 같이 const를 붙여서 매개변수를 값으로 전달할 경우, 매개변수 자체는 변경할 수 없지만 여전히 복사 생성자 호출 시 값 복사가 발생합니다.
- 결과: 이렇게 하면 1번과 마찬가지로, 복사 생성자 호출 시 내부적으로 다시 복사 생성자가 호출되는 무한 재귀 호출 문제가 발생합니다. 즉, const를 추가했더라도 값 복사 방식이기 때문에 무한 재귀 호출 문제가 해결되지 않습니다.
3번 Copycat(const Copycat& cc) (올바른 선택)
- 이유: const Copycat& cc와 같이 상수 참조를 통해 매개변수를 전달하면, 객체를 복사하지 않고 원본 객체를 참조하므로 무한 재귀 호출 문제를 피할 수 있습니다.
- const의 역할: const를 붙여 원본 객체를 수정할 수 없도록 보장하며, 안전하게 객체를 참조할 수 있습니다.
- 결과: 상수 참조로 전달하여 복사 생성자가 정상적으로 동작하며, 복사된 데이터가 name 포인터를 통해 올바르게 초기화됩니다.
'수업 > C++' 카테고리의 다른 글
8,9연산자 다중정의 (0) | 2024.11.25 |
---|---|
7.클래스와 객체 -임시객체,묵시적형변환,위임생성자 ,초기화리스트생성자 (0) | 2024.11.25 |
4강 함수 (1) | 2024.10.01 |
3강 C++기초 // C++의 구조체, 동적 메모리할당 (0) | 2024.10.01 |
1강2강 c++소개 (1) | 2024.09.30 |