stl map 내부에 특정 key 존재 여부 확인법?

ssehoony의 이미지

STL 의 map 을 사용할려고 하는데요
특정 key 값을 갖는 데이터가 기록되어있는지 아닌지의 여부를
어떻게 확인할 수 있나요?
맵의 맴버 함수인 map_xxx.find(key) 로 iterator 을 반환 받을 때
map 에 없는 key 를 찾길 요구하면 iterator 에 무슨 값이 들어가나요?

그리고 또
value = map_xxx[key];
라고 접근 할 수도 있자나요.
이때 key 가 존재하지 않는다면 value 의 값은 어떻게 되는건가요?

제가 본 레퍼런스는 존재할 경우의 리턴값만 설명되어 있고
없을때의 경우에 대해서는 설명이 없어서 이렇게 질문 드립니다.

ixevexi의 이미지

첫번째 질문에서 실패할 경우는
아마도! end()가 반환하는 값이 될 겁니다.
즉 제일 마지막 원소의 !뒤!(past- the - end)를 가리키는 값입니다.

실패여부를 알아보실려면
itor = map_xxx.find(key);

if( itor != map_xxx.end() )
여기에 쓰시면 ^_^

그리고 [key]가 없을 경우는 저도 궁금하군요
분명히 읽었던것 같은데 코드에 써본적이 없어서 ㅠ.ㅜ
제 생각에는 아무리 그래도 exception을 던지지는 않을 듯 합니다.
그저 0정도가 적당하지 않을까 하는데요ㅕ
집에 정확히 레퍼런스 찾아보고 다시 올리겠습니다.

C++, 그리고 C++....
죽어도 C++

ifyou의 이미지

저도 stl 초보인데..

방금해 보니까, int 일 경우에는 "0"을, string일때에는 NULL을

이네요. 아마 c에서 전역변수처럼 초기화를 하는 듯합니다 :lol:

ssehoony의 이미지

오~ 그렇군여.
좋은 답변 감사합니다. ^^

pynoos의 이미지

find 로 있는지 확인하지 않고 [] 연산자를 사용하면 키가 없는 경우 항상 디폴트 생성자로 값을 만들어 해당 키를 넣습니다.

1.
따라서 주의 할 것은 [] 연산자가 const 멤버함수가 아닌것이죠.

구현 할 때, const 로 map을 받았다면, 또는 const 멤버 함수에서 멤버 변수로서의 map을 받았다면, (둘은 같은 말이죠)
[] 연산자를 쓸 수 없고 const_iterator를 통해 값을 찾은뒤 second 로 얻어야합니다.

2.
또한 return 하는 type도 사용자가 읽기만 할지 쓰기까지 할 것인지 모르기 때문에 const아닌 reference를 넘기게 됩니다.

return type에 의한 함수 오버로딩이 되지 않기 때문에 아마 위 두 issue는 상호 연관되어 있는 듯합니다.

girneter의 이미지

일단 find() 로 검색하시면

Quote:

itor = map_xxx.find(key);

if( itor != map_xxx.end() )

로 확인하시는게 맞구요.

[] 로 했을 경우에는
0 이나 NULL 로 확인하시면 됩니다.

그런데 이렇게 [] 를 이용하여 검색하면 key 가 map 에 없을 때
자동으로 make_pair(key, 0) 가
map 에 추가되어 버립니다.

이로 인해서 부작용이 발생할 수도 있거든요.
물론 그걸 알고서 잘~ 짜면 되긴 하지만...

저 같은 경우는 저걸 모르는 상태에서 몇 일 삽질한 이후로
pair 를 대입할 때나 key 값이 있는게 확실한 경우에는 [] 를 사용하고
보통 검색할 때는 귀찮아도 find() 를 사용합니다.

개념없는 초딩들은 좋은 말로 할때 DC나 웃대가서 놀아라. 응?

pynoos의 이미지

girneter wrote:

[] 로 했을 경우에는
0 이나 NULL 로 확인하시면 됩니다.

그런데 이렇게 [] 를 이용하여 검색하면 key 가 map 에 없을 때
자동으로 make_pair(key, 0) 가
map 에 추가되어 버립니다.

그렇지 않습니다.

vi /usr/include/g++-3/stl_map.h

42 template <class _Key, class _Tp, class _Compare = less<_Key>,
     43           class _Alloc = __STL_DEFAULT_ALLOCATOR(_Tp) >
     48 class map {

    150   _Tp& operator[](const key_type& __k) {
    151     iterator __i = lower_bound(__k);
    152     // __i->first is greater than or equivalent to __k.
    153     if (__i == end() || key_comp()(__k, (*__i).first))
    154       __i = insert(__i, value_type(__k, _Tp()));
    155     return (*__i).second;
    156   } 

Key가 발견되지 않을 때는,

__i = insert(__i, value_type(__k, _Tp()));

이렇게 구현하는군요... 즉 두번째 인자의 Type인 _Tp의 디폴트 생성자입니다.

만약 두번째가 int 라면..

int() 라는 생성자가 불리겠지요.

      1 #include <stdio.h>
      2 #include <map>
      3 
      4 int main()
      5 {
      6         printf("%d\n", int());
      7         return 0;
      8 }

0이 나옵니다.

즉 0 이라는 값이 들어가는 것이 아니라 int() 라는 값이 0 으로 초기화 되어 들어가는 것입니다. 만약 두번째 클래스가 사용자 정의 클래스라면 좀 달라지겠지요.

stl에서 키가 있다는 것을 확인하지 않고 read 용으로 [] 연산자를 사용하는 것은 제가 보기엔 범죄행위입니다.

제가 생각하기엔, 대입할 때 주로 사용하는 것이 좋으며,
container[1] = 2;
사실 이것은 대입이라기보다는 새로운 빈 pair를 insert하고 값을 바꾸는 행위입니다.

있다는 것을 확신할 때는 아마 iterator로 확인한 다음이므로 그 iterator를 사용하여 값을 iterator->second로 넣어 주면 될것 같습니다.

iterator 없이 값이 있다는 것이 확실하면, (전방에서 모종의 assert를 통과했다면) 바로 사용해도 좋습니다.

girneter의 이미지

pynoos wrote:

그렇지 않습니다.

vi /usr/include/g++-3/stl_map.h

42 template <class _Key, class _Tp, class _Compare = less<_Key>,
     43           class _Alloc = __STL_DEFAULT_ALLOCATOR(_Tp) >
     48 class map {

    150   _Tp& operator[](const key_type& __k) {
    151     iterator __i = lower_bound(__k);
    152     // __i->first is greater than or equivalent to __k.
    153     if (__i == end() || key_comp()(__k, (*__i).first))
    154       __i = insert(__i, value_type(__k, _Tp()));
    155     return (*__i).second;
    156   } 

Key가 발견되지 않을 때는,

__i = insert(__i, value_type(__k, _Tp()));

이렇게 구현하는군요... 즉 두번째 인자의 Type인 _Tp의 디폴트 생성자입니다.

만약 두번째가 int 라면..

int() 라는 생성자가 불리겠지요.

아.. 그렇군요.
간만에 잘 아는 거라고 답변을 올린건데.. :oops:

잘 배웠습니다. 고맙습니다.

개념없는 초딩들은 좋은 말로 할때 DC나 웃대가서 놀아라. 응?

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.