모 회사 면접 준비중에 예전에 당했던 문제가 생각나서 정리하려다, 문득 제대로 조사해본적이 없는거같아 기록용으로 작성한다.
사실, 검색해보다가 내가 시원하게 이해할만한 자료가 없었던것도 있고...
C에서 Char 형 배열 / 포인터로 겨우겨우 만들던 String에서 벗어나, 관리 함수등을 추가한 C++ String Class로 되면서, '어느정도는' 타 언어의 String 사용법과 비슷하게 이루어지기 시작했다. 물론, 문자열 다루는거는 Java 보다는 불편하긴한데, 이전 면접에서 '왜 불편한가요?' 라는 질문에 좀 어영부영 대답한 감이 없잖아 있는것같다.
따라서 포인터 개념이 살아있는 OOP인 C++과, 전부 GC로 관리되는 Java와 비교를 해보고자 한다.
1. C++ String의 경우 (wstring은 포함시키지 않음)
기본적으로 C++ String은 'Basic String' 이라는 자체 클래스를 내부에 구현한 상태로 되어있으며, Basic String의 생성자는 크게 'const Char *' 를 input으로 받는 경우, 자체 Allocator를 input으로 받는 경우(= 타 value_Type 배열포인터를 input으로 받는 경우), basic_string 참조값을 input으로 받는 경우로 나뉘어진다.
즉, 실제 구현에서는 '일단 모든 데이터형을 받을수 있도록' 구현이 되어있긴 하나, 문자열 자체를 받는경우는 여전히 Char 형 배열 포인터를 값으로 받는다... 고 설명할 수 있다.
그리고, String Class가 되면서, 각종 접근법 / 용량 체크 / 복사 / equal 등의 함수가 가능해졌다.
아래부터는 String str = "Hello World"; 라는 String을 선언해둔것으로 가정하고 시작한다.
1) 접근법
str.at(N) = N번 자리의 문자열을 리턴해준다.
str.at(1) 을 사용시, 1번째 값인 e를 리턴해주게 된다.
str[N] = N번 자리의 문자열을 리턴해준다.
str.at(N)과 다른게 뭐냐고 한다면, 둘다 결국엔 str[N]으로 귀결되는건 동일하나,
basic_string<_CharT, _Traits, _Allocator>::at(size_type __n) const
{
if (__n >= size())
this->__throw_out_of_range();
return (*this)[__n];
}
at()의 경우에는 잘못된 값 삽입 시 out of range() 경고를 리턴해주는 차이가 있다.
속도 자체는 자체 함수로 이동하지 않는 str[N]이 빠르긴 하나, 내가 짠 코드를 100% 믿을 수 있는게 아니라면 at()을 쓰는것을 추천한다...
2) 길이 파악
size() 함수와 length() 함수가 존재하는데...
_LIBCPP_INLINE_VISIBILITY size_type size() const _NOEXCEPT
{return __is_long() ? __get_long_size() : __get_short_size();}
_LIBCPP_INLINE_VISIBILITY size_type length() const _NOEXCEPT {return size();}
그냥 length 함수 호출해도, size를 호출해도 결국엔 size() 함수가 호출되는거니까 아무거나 써도 된다 (...)
3) 비교
str.compare() 이라는 함수가 있다.
str.compare("ABC") 와 같은 방식으로 사용이 가능한데...
일반적으로, '같으면 0', '함수를 호출한 String이 사전순으로 빠를때 -1', '사전순으로 느릴때 1' 의 값을 리턴하는것으로 알고 있을것이다.
이는 또 재밌게도,
basic_string<_CharT, _Traits, _Allocator>::compare(const _Tp& __t) const
{
__self_view __sv = __t;
size_t __lhs_sz = size();
size_t __rhs_sz = __sv.size();
int __result = traits_type::compare(data(), __sv.data(),
_VSTD::min(__lhs_sz, __rhs_sz));
if (__result != 0)
return __result;
if (__lhs_sz < __rhs_sz)
return -1;
if (__lhs_sz > __rhs_sz)
return 1;
return 0;
}
'일단' 두 String을 가져와 min 비교를 걸친 후 (String 별 호출순서 비교), 만일 min() 비교가 동일한것으로 나오면, 길이 비교를 진행, 이후 해당 값을 리턴해주는 식으로 진행된다.
즉, 만일 str.compare("Hello"); 를 넣어줬다면
Hello World / Hello 두 문자열의 비교 자체는 4번째 값인 o까지 비교를 하고, 그 이상은 비교가 불가능하니 if문으로 넘어가게 된다.
근데 여기서 좌측값 (= 함수를 호출한 String)의 길이가 더 길기때문에, 1을 리턴해주는것으로 결과가 종료되는것이다.
Min의 내부 구현은 (아스키코드 값의 경우) A값과 B값의 코드 순서로 비교를 수행하게된다.
자세한건 검색을 통해 찾아보시길...
아무튼, 요런 식으로 구현이 되어있는데, 위에 언급했다시피, '배열 포인터' 로 구현이 되어있기에, 문자열을 수정하면 해당 문자열 메모리 자체를 수정하는식으로 값을 수정하게 된다.
이것이 메모리 관리 관점에서 Java String과의 가장 큰 차이점이라고 볼 수 있기도 하다.
나머지는 다음장에... 생각보다 길어질거같아서 쪼개야할것같다.
https://code.woboq.org/llvm/libcxx/include/string.html
string source code [libcxx/include/string] - Woboq Code Browser
code.woboq.org
참고자료.
C++ 내부 구현을 기록해 둔 레퍼런스 사이트.
해당 글을 작성할때 참고한 페이지를 링크해두었다.
초보자가 볼 만한 사이트는 아니므로, 레퍼런스 자료가 필요하면 https://en.cppreference.com/를 참고하거나, 검색을 통해 한글로 설명된 다른 페이지를 참고하는걸 추천드린다..
'프로그래밍' 카테고리의 다른 글
내가 급해서 쓰는 컴퓨터공학 이론 간단 요약 (0) | 2020.06.18 |
---|---|
C++ String vs Java String 비교 : 3. 이제 진짜 비교를 해보자. (0) | 2020.04.29 |
C++ String vs Java String 비교 : 2. Java String에 대한 간략한 설명. (0) | 2020.04.29 |
Epsilon Delta (0) | 2020.04.19 |
기록해둘것 (0) | 2020.01.10 |