오늘의 TIL 목차 (22.08. 31)
- string 함수
- explicit
- 전방 선언
string 함수
[ string ]
: C++에 들어온 문자열 함수 ( 문자열 끝에 널( '\0' )을 포함하지 않음 )
#include <string> // string 헤더파일 포함
생성 방법
1.
string.str1("Dainn"); // string str1 = "Dainn";
2.
string str2; // 선언 ( 쓰레기값 )
str = "Dainn"; // 초기화
3.
string str3(str2); // 인자값 또는 문자열 넣어 문자열 생성 가능
■ 기능 / 주의
- string 문자열은 대입 연산자를 통해 대입이 가능하다 ( char 배열은 대입 불가능, 문자열 함수 이용해야 함 )
- string에 C 배열을 대입할 수 있지만 C 배열에 string 문자열을 대입할 수 없다. ( c_str()함수로 c로 바꿔주면 가능 )
- string은 '널'을 포함하지 않는다. length() 시 순수 문자열의 길이 출력
@. str.size(); // 문자열 str이 사용하고 있는 사이즈 반환 ( c의 strlen과 유사 ), 널 제외
@. str.length(); // 문자열 str의 길이 반환 ( size() 함수와 유사 ), 널 제외 순수 문자열
@. str.clear(); // 문자열 초기화
@. str.c_str() // C++ string을 C 스타일의 문자열로 변경해주는 함수
- strcpy_s 등 char 배열에 string을 대입하고 싶을 때 사용
[ size와 length의 차이 ]
size는 객체가 메모리에서 실제 사용하고 있는 크기
length는 널 제외 문자열의 길이
string s = "이다인"; // 한글은 한 글자당 2byte
cout << s.size() << "\t" << s.length() << endl; // 6 6
-> 외관상 보기에는 똑같음, 그러나 문자열의 길이를 구한다면 length를 사용할 것
■ 예시
string sName = "dainn";
string str("faimly");
char szName[10] = "locco";
//szName = sName;
cout << sName << endl;
// 문자열에 char 배열 locco 대입 가능
//string은 대입연산자로 대입 가능 (char 배열은 문자열 함수 이용해야함)
sName = szName; // sName에 locco 대입
cout << szName << endl;
// sName(str); 불가능
sName = str; // sName에 family 대입
// C배열에 string대입 불가능, c_str()함수를 이용하여 C언어로 전환 후 가능
strcpy_s(szName, sizeof(sName), sName.c_str()); // locco를 C로 전환 후 szName에 대입
cout << szName << endl;
cout << sName.length() << "\t" << sizeof(szName) << endl; // sName은 family, szName은 loccol;
sName.clear(); // 문자열 초기화
cout << sName << endl; // sName은 초기화됨
출력 결과 :
dainn
locco
family
6 10
빈칸
전방선언
[ 전방선언 ]
: 식별자를 정의하기 전에 식별자의 존재를 컴파일러에게 미리 알리는 방식
#include "Student.h" 대신
class cStudent; 로 사용되는 클래스 명만 선언
- 헤더파일의 의존성을 회피 ( 헤더파일이 증가할수록 재컴파일 양이 많아져 속도 저하 )
- 상호 참조가 발생하여 자료형의 크기를 정확히 알 수 없거나 무한루프가 걸리는 문제를 해결하기 위한 문법
- 소멸자에 소멸자를 호출하면 무한루프에 빠짐 ( 소멸자에 Release()를 넣어주는 이유이기도 함 )
■ 기능 / 주의
- 전방 선언을 할 경우 그 클래스 관련 객체는 무조건 포인터형으로 선언
- 컴파일러는 자료형의 종류와 크기를 파악해야 하는데 전방 선언 시 내부가 노출되지 않아 크기를 알 수 없기 때문에
4byte 크기인 포인터로 객체를 생성하여 크기를 알 수 있도록 할당해줘야 함 - 전방 선언을 한 .cpp 파일에 꼭 해당 헤더파일을 include, 인스턴스 생성을 위해서 클래스 정보를 알아야 하기 때문
- 전방 선언은 멤버 함수와 멤버 변수의 유무를 알 수도 호출 할 수도 없음 ( 불필요한 정보를 노출하지 않는다는 장점 } - 헤더와 헤더 사이에서 문제가 되는 것이지 .cpp에서는 헤더를 포함해도 상호 참조 문제가 발생하지 않음
- 전방선언은 상호 참조를 방지하기 위함이니 너무 남발하지 말것
void main(void)
{
explicit
[ explicit ]
: 생성자를 통해 암묵적 형 변환(자동 형 변환)이 일어나는 것을 막아주는 기능
■ 기능 / 주의
- explicit는 묵시적 형 변환이 발생하는 생성자 앞에 붙여서 사용한다.
- 생성자 앞에 explicit 키워드를 붙이면 C 기반의 초기화 ( =을 이용한 초기화 )를 막는다.
class CDainn
{
public:
CDainn() {} // 1 생성자
explicit CDainn(int _i) : m_i(_i), m_c(0) {} // 2 생성자
CDainn(int _i, char _c) : m_i(_i), m_c(_c) {} // 3 생성자
public:
int m_i;
char m_c;
};
// CDainn이 들어와야하는데 10이 들어오면 2 생성자를 실행시켜 CDainn으로 묵시적 형변환
// 만약 2생성자가 없었다면 오류 발생
// 이를 방지하는 것이 묵시적 형변환이 발생하는 2 생성자에 explicit를 붙여주는 것
void Print(CDainn _cd) // 전역 함수
{
cout << _cd.m_i << ". " << _cd.m_c << endl;
}
void main(void)
{
Print(10); // CDainn타입을 받는 매개변수에 int를 넘겨줌
=> 10이 묵시적으로 형 변환되어 CDainn의 int를 받는 생성자를 통해 생성된 후 Print() 실행
=> explicit를 붙여 이를 방지함
CDainn cd = 10; // 오류, explicit로 C기반의 초기화를 막음, 원래였음 2 생성자 호출됨
CDainn cd(10); // explicit로 인해 오직 C++ 기반의 초기화만 허용
}'C++' 카테고리의 다른 글
| [TIL 22장] 동적할당(깊은 복사, 얕은 복사), 복사 생성자, extern, friend (0) | 2022.09.05 |
|---|---|
| [TIL 21장] 이니셜라이저, const 멤버 변수/함수, static 멤버 변수/함수, this (0) | 2022.09.02 |
| [TIL 19장] 클래스 특성 - 캡슐화, 클래스 - 생성자, 소멸자 (0) | 2022.08.30 |
| [TIL 18장] OOP의 개념(+추상화), 클래스(4대 속성), 클래스 속성 - 은닉화(feat. 접근 제어 지시자), 파일 분리 (클래스 - 선언부 구현부) (0) | 2022.08.29 |
| [TIL 16장] 레퍼런스 (0) | 2022.08.18 |