반응형
std map 올바른 사용법
std::map<int, Class *> map 을 사용할 때 생각보다 어이없는 부분에서 문제가 발생한다.
쉽게 생각하고 넘기지만 프로그램이 종료되기도 하기 때문에 정확히 알고 사용하는 것이 중요하다.
결론 요약 정리
- insert를 할 때 :
틀린 방법: map.at(key)= new A()
옳은 방법: map[key] = new A()
-> 위의 틀린 방법으로 아이템을 추가할 경우, at 은 내부적으로 바운더리 체크가 있기 때문에 out of range exception이 발생하게 된다. at()은 아이템에 접근할 때만 사용한다.
-> operator[ ]는 아이템에 접근하고 추가할 때 모두 사용할 수 있다.
- 삭제할 때:
틀린 방법:
delete map[key]
옳은 방법:
auto value = map[key]
delete value
map.erase(key)
-> delete map[key]를 하면 해당 주소의 객체가 삭제되긴 하지만 map에서 위치 주소를 여전히 저장하고 있다. 따라서 아이템을 확인하면 존재하는 걸로 나오게 된다.
- 존재 확인할 때:
틀린 방법: map.find(key) != map.end()
옳은 방법: map.contains(key) (c++20)
-> contains는 c++20버전부터 지원한다. 따라서 하위 버전일 경우 map[key]로 존재 여부를 확인할 수도 있다.
테스트 방법
#include <iostream>
#include <map>
using namespace std;
class A {
public:
A(std::string str){
this->str_ = str;
};
~A() {
};
std::string str_;
};
void print_map(std::string_view comment, std::map<int, A*> m)
{
std::cout << comment;
// iterate using C++17 facilities
for (const auto& [key, value] : m)
std::cout << '[' << key << "] = " << value << "; ";
std::cout << '\n';
}
int main()
{
std::cout << "Hello Deleting a Item of Map World" << std::endl;
std::map<int, A*> map_;
map_[0] = new A("test 0");
map_[1] = new A("test 1");
map_[2] = new A("test 2");
map_[3] = new A("test 3");
// map의 item 삭제 방법 1
std::cout << "==================== Way1. delete map[n] ====================" << std::endl;
auto p0 = map_[0];
delete map_[0];
if (map_[0]) {
std::cout << "'delete map[0]' and 'map[0]' doesn't work." << std::endl;
} else {
std::cout << "'delete map[n]' and 'map[0]' works." << std::endl;
}
if (map_.find(0) != map_.end()) {
std::cout << "'delete map[n]' and 'map.find(0)' doesn't work." << std::endl;
} else {
std::cout << "'delete map[n]' and 'map.find(0)' works." << std::endl;
}
if (p0) {
std::cout << "'delete map[0]' doesn't work. object p[0] exists" << std::endl;
}else {
std::cout << "'delete map[0]' works. object p[0] dosen't exist" << std::endl;
}
// map의 item 삭제 방법 2
std::cout << "==================== Way2. map.erase(n) ====================" << std::endl;
auto p1 = map_[1];
map_.erase(1);
if (map_[1]) {
std::cout << "'map_.erase(1)' and 'map[1]' doesn't work." << std::endl;
} else {
std::cout << "'map_.erase(1)' and 'map[1]' works." << std::endl;
}
if (map_.find(1) != map_.end()) {
std::cout << "'map_.erase(1)' and 'map.find(1)' doesn't work." << std::endl;
} else {
std::cout << "'map_.erase(1)' and 'map.find(1)' works." << std::endl;
}
if (p1) {
std::cout << "'map_.erase(1)' doesn't work. object p[1] exists" << std::endl;
std::cout << "p1=" << p1->str_ << std::endl;
}else {
std::cout << "'map_.erase(1)' works. object p[1] dosen't exist" << std::endl;
}
// map의 item 삭제 방법 3
std::cout << "==================== Way3. delete and erase ====================" << std::endl;
auto p3 = map_[3];
delete p3;
p3 = nullptr;
map_.erase(3);
if (map_[3]) {
std::cout << "way3 and 'map[3]' doesn't work." << std::endl;
} else {
std::cout << "way3 and 'map[3]' works." << std::endl;
}
if (map_.find(3) != map_.end()) {
std::cout << "way3 and 'map.find(3)' doesn't work." << std::endl;
auto iter = map_.find(3);
std::cout << "found: " << iter->first << "," << iter->second << std::endl;
} else {
std::cout << "way3 and 'map.find(3)' works." << std::endl;
}
// print
std::cout << "==================== Print map ====================" << std::endl;
print_map("", map_);
/*for(auto iter = map_.begin(); iter != map_.end(); iter++)
{
std::cout << "("<< iter->first << "," << iter->second << ")"<< endl;
}*/
return 0;
}
테스트 결과
반응형