const 키와 non const 키의 차이점은 무엇입니까?


답변:


65
  • int그리고 const int두 가지 종류가 있습니다.

  • std::map<int, float>와 std::map<const int, float>, 마찬가지로 다른 유형입니다.

std::map<const int, float>and 사이의 차이 std::map<int, float>는 어느 정도는 say std::map<int, float>와 사이의 차이와 유사합니다 std::map<std::string, float>. 각각에 대해 새로운지도 유형을 얻습니다.

const그렇지 않은 경우 내부 키 유형 은 여전히 const int다음과 같습니다.

std::map<const int, float>::key_type       => const int
std::map<int, float>::key_type             => int

그러나 맵 키는 의미 상 불변이며 키에 대한 직접 액세스를 허용하는 모든 맵 작업 (예 : 이터레이터 역 참조 value_type)은 다음을 수행 const합니다 key_type.

std::map<const int, float>::value_type => std::pair<const int, float>
std::map<int, float>::value_type       => std::pair<const int, float>

따라서 구현에서 허용하는 경우 중요한 모든 방식에서 차이 가 거의 보이지 않을 수 있습니다.

하지만 항상 그런 것은 아닙니다. 표준은 공식적으로 키 유형을 복사 및 이동 가능하도록 요구 하며 일부 구현에서는 맵 노드를 재사용합니다 . 이러한 구현에서 const키 를 사용하려는 시도 는 작동하지 않습니다.


1
So the difference is largely invisible to you in every way that matters.-키 (libc ++ 등)를 복사 / 이동하는 stdlib를 사용하지 않는 한,이 경우 const 버전이 중단됩니다. 관련 토론 은 목록 .cs.uiuc.edu / pipermail / cfe-dev / 2011-July / 015926.html 을 참조하십시오 .
— mitchnull 2014 년

@mitchnull 네, 좋은 자리입니다. ( btw !)
— 궤도

@LightnessRacesinOrbit "표준은 공식적으로 키 유형을 복사 및 이동 가능하도록 요구합니다". 움직일 수 있다는 것에 대해 제가 가지고있는 C ++ 표준 사본에서 찾을 수 없습니다. 참조 또는 섹션 번호를 제공해 주시겠습니까?
— beren

이것은 훌륭한 대답이며, 마침내 const지도와 관련하여 내가 가진 전체적인 문제를 명확히했습니다 . C ++ 14는 우리를 예리하게 유지하기 위해 약간의 복잡성을 추가하는 투명한 비교기 를 도입했습니다. :)
— vsoftco

아, 키가 const가 될 수 없음을 확인해 주셔서 감사합니다. 내 키는 불변되고 싶어 그리고 그것은 나를 견과류 -_- 몰았다
— 노엘 년 Widmer

36

키는 이미 const그것을 쓸 중복하므로, const이 경우. 한 번 입력 된 요소는 key변경할 수 없습니다.


편집 :

코멘트에서 언급 한 바와 같이,이 인 두 줄의 차이. 예를 들어를 받아들이는 함수를 작성하면 서로 다른 유형 이므로 map<const int, int>전달할 수 없습니다 .map<int, int>

그러나 그들은 다른 유형이지만 맵의 키가 const어쨌든 동일하기 때문에 동일하게 작동 합니다.

결론적으로 .. 유일한 차이점은 두 가지 유형이라는 것입니다. 다른 것은 신경 쓰지 말아야합니다.


18
이것은 (완전히) 정확하지 않습니다. 의 인터페이스는 std::map키 유형을로 노출 const하지만 두 템플릿 인스턴스화가이 답변이 의미하는 것과 동일하다는 것을 의미하지는 않습니다. std::map<const int, float>하고 std::map<int, float>있는 다른 유형 .
— jrok 2013

1
@jrok은 정확하지만이 대답은 그렇지 않습니다. 은 key_type여전히 사실이다 int전자의 경우에.
— 궤도의 가벼운 경주

6
@ johnmac2332 : 이것이 빠르고 완벽하고 찬성표를 던지는 교훈이되도록합시다! = 맞습니다.
— 밝기 경주 궤도에

1
@ johnmac2332 빠르고 빠른 답변은 높이 평가되어야합니다. 이것은 다른 웹보다 우수한 Stackoverflow 품질 중 하나입니다. OP는 주석 섹션에서 추가 쿼리를 할 수 있습니다. 그가 고맙다고 말한다면 아마도 그가 답을 얻었다는 뜻입니다.
— Grijesh Chauhan 2013

2
완벽한 사람은 없습니다. 우리 모두는 실수를하고 서로에게서 배웁니다. 우리는 :) 배우고을 도와 드릴까요?
— Maroun

8

차이점은 두 번째 변형은지도의 키 유형을로 설정한다는 것입니다 const int. "수정 가능성"의 관점에서 볼 때 맵은 이미 키를 const객체 로 저장하기 때문에 중복 됩니다.

그러나 이로 인해이 두 맵의 동작에서 예상치 못한 명백하지 않은 차이가 발생할 수도 있습니다. C ++에서 type 용으로 작성된 템플릿 전문화는 type T용으로 작성된 전문화와 다릅니다 const T. 즉, 위의 두 버전의지도는 키 유형에 따라 다양한 "위성"템플릿의 다른 전문화를 사용하게 될 수 있습니다. 한 가지 예는 키 비교기 술어입니다. 첫 번째는를 사용 std::less<int>하고 두 번째는 std::less<const int>. 이 차이를 활용하면 이러한 맵을 쉽게 다른 순서로 요소를 정렬 할 수 있습니다.

이와 같은 문제는 std::unordered_map. 키를 해싱 std::unordered_map<const int, int>하기 위해 std::hash<const int>특수화 를 사용하려고 시도하기 때문에 컴파일조차하지 않습니다 . 이러한 전문화는 표준 라이브러리에 존재하지 않습니다.



2

응용 프로그램의 동작은 일반적으로 동일하지만 사용할 수있는 일부 컴파일러에 차이가 있습니다. 이 페이지를 처음 방문하게 된 구체적인 예는 다음과 같습니다.

map<const key, value>gnu 툴킷을 사용하여 성공적 으로 빌드 된 맵을 명시 적으로 지정합니다 .

그러나 Studio12 Solaris x86 빌드가 충돌합니다.


map<key, value>둘 다에서 성공적으로 구축됩니다. 응용 프로그램의 동작은 변경되지 않습니다.


어떤 방식으로 "충돌"?
— 궤도에서 가벼운 경주

@LightnessRacesinOrbit std::map::insert여러 선언을하는 것에 대해 불평했습니다 .
— blgt

예, 위에서 언급했듯이 컴파일러에 차이가 있습니다.
— blgt

일반적으로 "충돌"이라고하면 프로세스의 예기치 않은 비정상적인 런타임 종료를 의미합니다. 컴파일러 충돌은 드물지만 발생하며 (특히 새로운 언어 기능에서) 발생하며 (빌드 결과가 진행됨에 따라) 본질적으로 매우 심각합니다.
— 궤도

그것은 충돌 내 빌드 가 아닌 응용 프로그램을 . 용어를 잘못 사용하고 있습니까?
— blgt

0

Const 키는 키가 포인터 인 경우 유용 할 수 있습니다. const 키를 사용하면 키에 액세스 할 때 뾰족한 개체를 수정할 수 없습니다. 다음을 고려하세요.

#include <map>
#include <string>

int glob = 10;

int main() {
    std::map<const int*, std::string> constKeyMap { { &glob, "foo"} };
    std::map<int*, std::string> keyMap { { &glob, "bar" } };

    for(const auto& kv : keyMap) { *(kv.first) = 20; }; // glob = 20
    for(const auto& kv : constKeyMap) { *(kv.first) = 20; }; // COMPILE ERROR

    return 0;
}

1
(가) 때 key_type이다 const int*, 포인터하지 CONST 자체를하지만 뾰족한는 intCONST입니다.
— lrineau 2014-04-02

-1

const는 한 번 정의되면 변경할 수없는 상수를 나타냅니다. const가 아닌 키는 변경 될 수 있습니다 ... 또는 변경할 수 없습니다. const (한 번 정의 된 경우)에서 "변경 없음"이 보장됩니다. , 그리고 "변경"은 비 const 항목에서 발생하거나 발생하지 않을 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.