2008-11-04 3 views
85

다음 코드는 operator[] 방법에 const로지도를 통과하는 규정을 삭제 있다고? 지도 액세스 권한이있는 함수를 const로 선언 할 수 있습니까?C++지도 액세스를 파기 예선 (CONST)는

MapWrapper.cpp:10: error: passing ‘const std::map<int, int, std::less<int>, std::allocator<std::pair<const int, int> > >’ as ‘this’ argument of ‘_Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const _Key&) [with _Key = int, _Tp = int, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, int> >]’ discards qualifiers

+0

그냥 nitpick,하지만 MW는 MapWrapper 단순히 선언 할 수 있습니다 mw; – luke

+0

좋은 지적 - 몇 가지 언어로 작성하므로 문법을 표준화하여 머리에 맞도록하는 경향이 있습니다. :) – cdleary

+0

나는 그것을 알 수있다. 하지만이 경우에는 필요하지 않은 추가 객체 생성 및 할당이있는 경우에는주의해야합니다. – luke

답변

118

std::map's operator [] is not declared as const, and cannot be due to its behavior:

T & 연산자 [] (CONST 키 & 키)

는 키가 아직없는 경우의 삽입을 수행하는 키에 해당하는 키에 대응하는 값에 대한 참조를 반환 있다.

결과적으로 사용자의 기능을 const으로 선언 할 수없고지도의 operator[]을 사용할 수 없습니다.

std::map's find() 기능을 사용하면지도를 수정하지 않고도 키를 조회 할 수 있습니다.

find() 키 (.first)과 값 (.second) 모두를 포함하는 std::pairiterator 또는 const_iterator 반환한다.

C++ 11에서는 을 std::map으로 사용할 수도 있습니다. 요소가 존재하지 않으면 함수는 operator []과 반대로 std::out_of_range 예외를 발생시킵니다.

+6

추가적으로 : VALUE = map.find (KEY) -> second; 나는 find()가 iterator를 반환한다는 것을 배워야했다. iterator는 pair 형이다. – FlipMcF

+4

이제 C11에서 std :: map :: at (key)를 사용하여 이터레이터를 피할 수 있습니다. –

+2

흥미 롭습니다. C++에서는 lvalue 연산자 [] (예 :'foo [bar] = baz')와 rvalue'연산자 []'(예 :'x = foo [bar]')를 구별 할 수 있다고 생각합니다. – Claudiu

10

당신은 당신이지도를 수정할 수로에서 const되지 않도록 방법으로 const를하는지도 연산자 []를 사용할 수 없습니다 (당신이 _MAP에 할당 할 수있는 [키]). 대신 find 메소드를 사용해보십시오.

+1

설명의 방법 :지도의 연산자 []는 키가 존재하지 않으면 어떻게해야합니까? 맵이 const가 아닌 경우 키에 기본 생성 값이 추가됩니다. 지도가 const 인 경우 연산자 []에서 반환 할 수있는 항목은 무엇입니까? 그 열쇠에는 가치가 없습니다. – Arkadiy

7

일부 새로운 버전의 GCC 헤더 (내 컴퓨터의 4.1 및 4.2)는 const로 선언 된 비표준 멤버 함수 map :: at()을 가지고 있으며 키가지도에없는 경우 std :: out_of_range를 내 보냅니다.

const mapped_type& at(const key_type& __k) const 

함수 주석의 참조에서 표준 라이브러리의 새 멤버 함수로 제안 된 것처럼 보입니다.

+0

그건 좀 이상하지. at 함수는 다가오는 표준의 일부입니다 만, 현재의()에서는 no를 발견합니다. –

+0

버그 보고서 제출 : http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46544 –

+0

'at'은 C++ 11의 일부입니다. –

0

먼저 언어 구현/컴파일러 작성자에게 예약되어 있으므로 _로 시작하는 기호는 사용하지 않아야합니다. _map이 누군가의 컴파일러에서 구문 오류가되는 것은 매우 쉽습니다. 그리고 자신을 비난 할 사람은 아무도 없습니다.

밑줄을 사용하려면 시작 부분이 아니라 끝에 둡니다. 일부 Microsoft 코드가 그것을 보았 기 때문에 아마도이 실수를했을 수 있습니다. 자신의 컴파일러를 작성하므로 잊어 버릴 수도 있습니다. 그럼에도 불구하고 나쁜 생각입니다.

연산자 []는 참조를 반환 할뿐만 아니라 실제로지도에 항목을 만듭니다. 따라서 매핑을 얻는 것이 아니라 아무것도없는 경우 매핑을 생성하는 것입니다. 그건 당신이 의도 한 것이 아닙니다.

+4

'_'에 대한 당신의 요지가 잘못되었습니다. 두 개의 밑줄 ('__example')로 시작하는 식별자 또는 하나의 밑줄과 대문자 ('_Example')로 시작하는 식별자는 예약되어 있습니다. '_example'은 예약되어 있지 않습니다. – Ethan

9

operator[]에는 const 한정 과부하가 없으므로 const 한정 함수에서 안전하게 사용할 수 없습니다.이는 현재의 과부하가 키 값을 반환하고 설정하는 목표로 작성 되었기 때문일 수 있습니다. 대신

, 당신은 사용할 수 있습니다 : C++ 11,

VALUE = map.find(KEY)->second; 

또는, 당신은 at() 연산자를 사용할 수 있습니다

VALUE = map.at(KEY); 
관련 문제