문자열 총정리
C- style의 char와 C++ style의 string이 있다. 하나씩 확인해보자.
C - style
- char Array 사용
char a[6] = { 'a', 'b', '\n', 'c', 'd', 'e' };
cout << sizeof(a) << endl; // 6 바이트
cout << strlen(a) << endl; // 2 (null char 전까지)
char b[] = "abcdef"; // 자동으로 \n 추가됨.
cout << sizeof(b) << endl; // null char까지 7 바이트
cout << strlen(b) << endl; // 6
컴파일러에 따라 다르겠지만 문자열을 스택에 올리는 방법은 스택에 바로 올리는 방법 혹은 실행 중에 readonly 영역에서 해당 문자열을 복사해오는 방법이 있다. 중요한점은 최종적으로 문자열은 스택안에 들어간다는 것이 중요하다.
- char* 사용
char* c = "abcdef";
cout << sizeof(c) << endl; // 8 바이트 -> 포인터이기 때문
cout << strlen(c) << endl; // 6
이 때 c 는 스택 위에 올라가 있고 이 포인터는 readonly 영역의 "abcdef" 문자열을 가리킨다.
이를 이용해 잠깐 테스트를 해보면,
a[0] = 'g'; // a는 gbcdef로 변경됨 -> 스택에 있기 때문에 쉽게 변경 가능
c[0] = 'g'; // segmentation fault 에러 발생 -> readonly 영역에 있기 때문에 불가능
이와 같이 char* 를 사용하는 경우에는 문자열 변경이 불가능하다 따라서, char *를 사용해서 문자열을 만들 때는 const 를 꼭 붙여줘야한다.
C++ Style의 std::string
std::string s = "abcdef";
cout << sizeof(s) << endl; // 40 바이트
cout << s.size() << endl; // 6
- string은 클래스 템플릿이기 때문에 풍부한 기능 사용이 가능하다.
- string 같은 경우에는 null char를 사용해서 끊지 않기 때문에 문자열 안에 넣는 것도 가능하다.
- string은 스택이나 readonly가 아닌 Heap 메모리를 사용한다.
- vector처럼 자유롭게 변경이 가능하지만 힙을 사용하기 때문에 메모리 할당, 해제 등에 대한 Performance는 손해가 있을 수 밖에 없다.
위에서 string의 사이즈는 40 바이트인데 이는 컴파일러마다 다르다. (리눅스에서는 32바이트)
즉, string object의 크기는 굉장히 크다는 것이다. 이 때, 컴파일러마다 다르지만 string은 최적화가 적용될 수 있다.
string을 매번 힙에서 메모리 할당, 해제를 하는 것이 아니라 32 byte 혹은 40 byte 안에 충분히 들어갈 수 있다면 바로 string object안에 문자열을 넣는 것도 가능하다. 컴파일러마다 다르므로 이를 맹신해서 코드를 짜면 안된다.
결론
performance가 민감한 곳에서는 const char*를 사용하고 일반적인 곳에서는 std::string을 사용하면 된다.
'C++ > Modern C++' 카테고리의 다른 글
[C++] Perfect forwarding (0) | 2022.10.05 |
---|---|
[C++] constexpr (0) | 2022.10.05 |
스마트 포인터 문제 - 순환 참조 (0) | 2022.10.03 |
[C++20] std::span (0) | 2022.10.01 |
[C++17] string_view (0) | 2022.09.07 |