[STL]당쵀 이해가 되지 않습니다.(제목 정하기가 너무

assa의 이미지

소스를 봐주세요..

#include <iostream>
#include <map>
using namespace std;

void add_int(map<char *, int> &tmap, char *a, int i);

void main(void)

{
	map<char *, int> tmap;
	char *a= "a";

	for(int i= 0; i < 10; i++){
		add_int(tmap, a, i);
	}

	map<char *, int>::iterator map_i;
	map_i= tmap.find(a);

	if(map_i != tmap.end())
		cout << "not end" << endl;
	else
		cout << "end" << endl;

	cout << tmap.size() << endl;

} 

void add_int(map<char *, int> &tmap, char *a, int i)
{

     tmap.insert(pair<char *, int >(a, i));
}

이렇게 하면

결과가 ...

not end
1

이 나옵니다.

그런데

#include <iostream>
#include <map>
using namespace std;

void add_int(map<char *, int> &tmap, char *a, int i);

void main(void)

{
	map<char *, int> tmap;
	char *a= "a";

	for(int i= 0; i < 10; i++){
		char *c= new char[10];
		strcpy(c, a);
		add_int(tmap, c, i);
	}

	map<char *, int>::iterator map_i;
	map_i= tmap.find(a);

	if(map_i != tmap.end())
		cout << "not end" << endl;
	else
		cout << "end" << endl;

	cout << tmap.size() << endl;
} 

void add_int(map<char *, int> &tmap, char *a, int i)
{

     tmap.insert(pair<char *, int >(a, i));
}

이렇게 하면 결과가

end
10

이렇게 나옵니다.

즉 tmap에 insert는 되었지만, 같은 문자열임에도 불구하고,

다른 문자로 인식되어 insert되는데요..

이는 map의 특징(중복 key 금지)과도 완전히 다른 성격이 있습

니다.

아무리 생각을 해봐도 왜 이렇게 되는지 답을 알수가 없는데요..

map뿐만 아니라 모든 container들은 이렇게 되는 건가요?

STL을 쓸 경우 strcpy는 무조건 쓸 수 없는건가요?

도움을 부탁드립니다.

p.s. 원인을 찾는데만 하루가 걸렸네요 ㅠㅠ..

cedar의 이미지

맵에서 키를 비교할 때는 디폴트로 operator<()로 비교합니다.
map<char*, int>라면 char 문자열을 비교하는 게 아니라, char* 주소 값 자체를 비교하는 겁니다.

첫번째 코드에서는 a가 항상 동일하기 때문에 하나만 삽입되었지만, 두번째에서는 루프를 돌때마다 c가 바뀌므로, 10개 모두 인서트됩니다.

STL을 쓸 때는 char* 문자열은 잊어버리고 std::string으로 대체하십시오.
(두번째 코드에서는 new[]로 할당한 메모리를 delete[]로 삭제하는 코드가 있어서 메모리 릭이 발생하는군요. :oops: )

map<string, int>의 경우에는 string::operator<()를 사용하기 때문에 기대한 대로의 동작이 나옵니다.

rhizome의 이미지

cedar님이 말씀하신 것처럼 맵에 원소를 집어넣을 때 포인터 변수를 이용해 키 값을 비교하기 때문이구요.

맵을 선언할 때 비교 함수자를 만들어서 포인터가 아닌 포인터가 가르키는 객체를 비교할 수 있게 하는 것이 가능합니다.

이펙티브 STL의 20번 항목에 이 밥법에 대한 설명이 나와 있습니다.

거짓말이 없다는 것은 현대성보다도 사상보다도
백배나 더 중요한 일이다.

assa의 이미지

고맙습니다.

"STL을 쓸때는 char *를 잊어라.."

이 말이 왠지 가슴에 와닿네요..

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.