std :: map에서 char *를 키로 사용
다음 코드가 작동하지 않는 이유를 알아 내려고 노력하고 외침 문자 *를 키 유형으로 사용하는 데 문제가 있는지 또는 왜 발생하는지 잘 모르겠습니다. 내가 사용하는 다른 모든 기능 (HL2 SDK에서)이 사용 char*
하는 사용 std::string
하면 불필요한 합병증이 많이 발생합니다.
std::map<char*, int> g_PlayerNames;
int PlayerManager::CreateFakePlayer()
{
FakePlayer *player = new FakePlayer();
int index = g_FakePlayers.AddToTail(player);
bool foundName = false;
// Iterate through Player Names and find an Unused one
for(std::map<char*,int>::iterator it = g_PlayerNames.begin(); it != g_PlayerNames.end(); ++it)
{
if(it->second == NAME_AVAILABLE)
{
// We found an Available Name. Mark as Unavailable and move it to the end of the list
foundName = true;
g_FakePlayers.Element(index)->name = it->first;
g_PlayerNames.insert(std::pair<char*, int>(it->first, NAME_UNAVAILABLE));
g_PlayerNames.erase(it); // Remove name since we added it to the end of the list
break;
}
}
// If we can't find a usable name, just user 'player'
if(!foundName)
{
g_FakePlayers.Element(index)->name = "player";
}
g_FakePlayers.Element(index)->connectTime = time(NULL);
g_FakePlayers.Element(index)->score = 0;
return index;
}
비교 펑터를 맵에 제공해야합니다. 문맥 포인터가 null로 끝나는 언어가 아닌 포인터를 비교합니다. 일반적으로지도 키가 포인터가되기를 원하는 경우입니다.
예를 들면 :
struct cmp_str
{
bool operator()(char const *a, char const *b) const
{
return std::strcmp(a, b) < 0;
}
};
map<char *, int, cmp_str> BlahBlah;
절대적으로 100 % 확신하지 않는 똑같은 포인터로char*
지도에 접근 할 수 없습니다 .
예 :
char *s1; // pointing to a string "hello" stored memory location #12
char *s2; // pointing to a string "hello" stored memory location #20
로지도에 액세스하면로 액세스 s1
하는 것과 다른 위치가 s2
있습니다.
두 개의 C 스타일의 주소를 사용할 수 있습니다. 그리고 그것은 map
내용이 아닌 포인터 를 비교합니다.
로 전환하는 데 필요한 비용은 std::map<std::string, int>
생각만큼 많지 않을 수 있습니다.
정말로 그러나 const char*
맵 키로 사용해야하는 경우 다음을 시도하십시오.
#include <functional>
#include <cstring>
struct StrCompare : public std::binary_function<const char*, const char*, bool> {
public:
bool operator() (const char* str1, const char* str2) const
{ return std::strcmp(str1, str2) < 0; }
};
typedef std::map<const char*, int, StrCompare> NameMap;
NameMap g_PlayerNames;
작업 할 수으로는 std::map<const char*, int>
있지만 const
포인터가 아닌 것을 사용해서는 안됩니다 ( const
키에 추가 된 문자열에 유의하십시오 ). 맵에서 키로 참조하는 곳에서 변경됩니다. (는 키를지도 만들어 키를 보호하지만 const
이것은 포인터가 가리키는 문자열이 아닌 포인터 만 구성합니다 .)
하지만 단순히 사용하지 않는 이유는 std::map<std::string, int>
무엇입니까? 그것은 두통없이 즉시 작동합니다.
a char *
를 사용하여 문자열을 사용하여 비교하고 있습니다. 그들은 동일하지 않습니다.
A char *
는 char에 대한 포인터입니다. 궁극적으로 값이에 대한 유효한 주소로 해석되는 정수 유형입니다 char
.
문자열은 문자열입니다.
컨테이너는 올바르게 작동하지만 키가 a char *
이고 값이 int
.
다른 사람들이 말했듯이, 실제로 필요한 경우 포인터를 키로 사용하는 원칙적으로 잘못된 것이 없지만이 경우에는 char * 대신 std :: string을 사용해야합니다.
이 코드가 작동하지 않는 또 다른 이유는 맵에서 사용 가능한 항목을 찾으면 동일한 키 (char *)를 사용하여 맵에 다시 삽입하려고하기 때문이라고 생각합니다. 해당 키가 이미 맵에 있으므로 삽입이 실패합니다. map :: insert ()의 표준은이 동작을 정의합니다 ... 키 값이 존재하면 삽입이 실패하고 매핑 된 값은 변경되지 않습니다. 그런 다음 어쨌든 삭제됩니다. 먼저 삭제 한 다음 다시 삽입해야합니다.
char *를 std :: string으로 변경하더라도이 문제는 남아 있습니다.
이 스레드가 꽤 오래되었다는 것을 알고 있으며 지금까지 모든 문제를 해결했지만 아무도이 문제를 제기하지 않았으므로 앞으로의 시청자를 위해 대답하겠습니다.
여러 소스 파일에서 요소를 찾으려고 할 때 char *를 맵 키로 사용하는 데 어려움을 겪었습니다. 요소가 삽입 된 동일한 소스 파일 내에서 모든 액세스 / 찾기가 제대로 작동합니다. 그러나 다른 파일에서 찾기를 사용하여 요소에 액세스하려고하면 확실히 맵 내부에있는 요소를 가져올 수 없습니다.
그 이유는 Plabo가 지적한 것처럼 포인터 (모든 컴파일 단위에는 자체 상수 char *가 있음)가 다른 cpp 파일에서 액세스 될 때 전혀 동일하지 않기 때문입니다.
이 비교 (지원하는만큼 어떤 키 유형을 사용하는 아무 문제가 없다 <
, >
, ==
) 및 할당.
언급해야 할 한 가지 사항- 템플릿 클래스를 사용하고 있다는 점을 고려하십시오 . 결과적으로 컴파일러는 char*
및에 대해 두 가지 다른 인스턴스화를 생성합니다 int*
. 두 가지 의 실제 코드 는 사실상 동일합니다.
따라서을 void*
키 유형으로 사용한 다음 필요에 따라 캐스팅하는 것을 고려 합니다. 제 의견입니다.
참고 URL : https://stackoverflow.com/questions/4157687/using-char-as-a-key-in-stdmap
'ProgramingTip' 카테고리의 다른 글
Emacs 또는 Vim 대 Eclipse가 제공하는 효율성은 무엇입니까? (0) | 2020.10.20 |
---|---|
명명 된 튜플에 독을 추가 할 예정입니까? (0) | 2020.10.20 |
IUnityContainer.Resolve (0) | 2020.10.20 |
Android- 회전시 WebView 다시로드 방지 (0) | 2020.10.20 |
MongoDb가 코드 100으로 종료 됨 (0) | 2020.10.20 |