키가 존재하지 않는 맵의 값을 읽으면 어떻게됩니까?


84
map<string, string> dada;
dada["dummy"] = "papy";
cout << dada["pootoo"];

정의되지 않은 동작으로 간주되는지 여부, 존재하지 않는 키를 요청할 때 어떻게 알 수 있는지 모르기 때문에 당황합니다. 대신 find를 사용합니까?

답변:


89

map::operator[]값에 대한 데이터 구조는 소정의 키에 대응하는 검색 결과, 복귀에 대한 참조.

찾을 수없는 경우 기본 생성 요소를 투명하게 만듭니다. (이 동작을 원하지 않는 경우 map::at대신 함수를 사용할 수 있습니다 .)

std :: map 메서드의 전체 목록은 여기에서 얻을 수 있습니다.

http://en.cppreference.com/w/cpp/container/map

다음은 map::operator[]현재 C ++ 표준 의 문서입니다 .

23.4.4.3 맵 요소 액세스

T& operator[](const key_type& x);

  1. 효과 : 맵에 x에 해당하는 키가 없으면 value_type (x, T ())을 맵에 삽입합니다.

  2. 요구 사항 : key_type은 CopyConstructible이고 mapping_type은 DefaultConstructible입니다.

  3. 반환 값 : * this의 x에 해당하는 mapping_type에 대한 참조.

  4. 복잡성 : 대수.

T& operator[](key_type&& x);

  1. 효과 : 맵에 x에 해당하는 키가 없으면 value_type (std :: move (x), T ())을 맵에 삽입합니다.

  2. 요구 사항 : mapping_type은 DefaultConstructible이어야합니다.

  3. 반환 값 : * this의 x에 해당하는 mapping_type에 대한 참조.

  4. 복잡성 : 대수.


나는 실제로 그것이 말하는 표준의 어느 곳도 찾지 못했습니다. 적어도 23.3.1.2 [lib.map.access] 또는 내가 확인해야 할 다른 곳은 아닙니다. 편집 : 분명히 나는 ​​표준의 이전 버전을보고 있었다. 내 실수.
Vlad Ciobanu

@VladCiobanu : 위는 23.4.4.3 그대로 복사되었습니다. 현재 버전을 사용하고 ISO/IEC 14882:2011(E)있습니까?
Andrew Tomazos 2012

21

key valueusing 인덱스 연산자 에 액세스하려고하면 []다음 두 가지가 발생할 수 있습니다.

  1. 지도에는이 key. 따라서 해당 key value.
  2. 지도에 key. 이 경우 자동으로 key를 사용하여지도에 추가합니다 null value.

"pootoo"지도에 키가 없습니다. 그래서 자동으로 추가됩니다 keyvalue = ""(빈 문자열). 그리고 프로그램은 빈 문자열을 인쇄합니다.

여기에서지도 크기가 1.

키를 검색하려면를 사용할 수 있습니다 . 키가 없으면 map_name.find()반환 map_name.end()됩니다. 그리고 더 이상 추가되지 않습니다 key.

[]키 값을 설정하고자 할 때 연산자 를 사용할 수 있습니다 .


7

정의되지 않은 동작이 아닙니다. 경우 operator []제공된 키 값을 찾을 수없는, 그 위치에서 하나를 삽입합니다.


6

operator []의 경우 존재하지 않는 키의 값에 액세스하려고하면 기본적으로 생성 된 새 값 객체가 맵에 배치되고 참조가 반환됩니다.


2

operator[]에 대한 map반환이 아닌 const를 참조 당신은 방법으로 당신이 당신의 두 번째 줄에 표시 한 것을 사용하여 지정할 수 있습니다. 이러한 방식으로 액세스하면 기본 구성 요소 value유형 이 생성됩니다 .

요소를 찾고 싶다면 더 나은 방법은

iterator find ( const key_type& x )

(또는 const 대안) <map>.end()키를 찾지 못하거나 컬렉션에 있는지 알고 싶다면 사용할 수있는 것과 동일한 반복자를 반환합니다.

size_type count ( const key_type& x ) const

키가 고유하므로 맵에 대해 항상 1 또는 0을 반환합니다.


1

연산자 []가 제공된 키에 대한 값을 찾지 못하면 해당 위치에 하나를 삽입합니다.

그러나 방문하여 not exist keymapKV [not_exist_key] .member_fun ()과 같은 멤버 함수를 호출하면 프로그램이 중단 될 수 있습니다.

다음과 같이 예제, 테스트 클래스를 제공하겠습니다.

struct MapValue{
    int val;

    MapValue(int i=0){
        cout<<"ctor: "<<i<<endl; val = i;
    }

    ~MapValue(){
        cout<<"dtor: "<<val<<endl;
    }

    friend ostream& operator<<(std::ostream& out, const MapValue& mv){
        cout<<"MapValue: "<<mv.val<<endl;
    }

    string toString(){
        cout<<"MapValue: "<<val<<endl;
    }
};

테스트 코드 :

cout<<"-------create map<int, MapValue>-------"<<endl;

map<int, MapValue> idName{{1, MapValue(1)}, {2, MapValue(2)}};

cout<<"-----cout key[2]-----"<<endl;
cout<<idName[2]<<endl;

cout<<"-----cout key[5]-----"<<endl;
cout<<idName[5]<<endl;

cout<<"------- runs here means, does't crash-------"<<endl;

아래와 같이 출력 :

-------create map<int, MapValue>-------
ctor: 1
ctor: 2
dtor: 2
dtor: 1
dtor: 2
dtor: 1
-----cout key[2]-----
MapValue: 2

-----cout key[5]-----
ctor: 0
MapValue: 0

-------runs here means, does't crash-------
dtor: 0
dtor: 2
dtor: 1

우리는 그것을 볼 수 있습니다 : idName에 삽입하기 idName[5]위해 map 구조 {5, MapValue(0)}를 호출합니다 .

그러나으로 멤버 함수를 호출 idName[5]하면 프로그램이 충돌합니다.

cout<<"-------create map<int, MapValue>-------"<<endl;

map<int, MapValue> idName{{1, MapValue(1)}, {2, MapValue(2)}};


idName[5].toString();  // get crash here.


cout<<"------- runs here means, doesn't crash-------"<<endl;

맵이, 다른 실수해야하기 때문에 충돌하지 않아야
isti_spl

0

out_of_range 예외를 확인하십시오 : http://www.cplusplus.com/reference/stdexcept/out_of_range/

이것이 key가 존재하지 않으면 map :: at과 map :: operator []가 던지는 것입니다. 링크의 벡터 예제와 같은 방식으로 잡을 수 있습니다.

http://www.cplusplus.com/reference/map/map/find/를 사용할 수도 있습니다.

그리고 map :: end를 확인하십시오.


4
no, only map :: at throws, map :: operator []는 키가 존재하지 않으면 새로운 value_type을 생성합니다
galka
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.