有希
std::map(set) insert 정확하게 사용하기 본문
출처: https://yonmy.com/archives/9
나나 다른 사람들의 코드를 보면 대부분 이렇게 쓰고 있다.
std::map<int, std::string> temp;
auto itr = temp.find(1);
if (itr == temp.end())
{
temp.insert({ 1, "number 1" });
}
else
{
itr->second = "number 1";
}
1. 우선 find
2. 찾지 못했다면 insert 찾았다면 값 change
이런 로직으로 된다. 하지만 위 표를 보면 리턴값으로 pair를 돌려주는 것을 알 수 있다.
즉, 위의 코드는 아래와 같이 바뀌어야 한다.
std::map<int, std::string> temp;
auto ret = temp.insert({ 1, "number 1" });
if (!ret.second)
{
ret.first->second = "number 1";
}
찾는 것이 아닌 어차피 insert 할 것이라면 처음부터 insert를 한다. 그리고 성공했으면 ret.second만 보면 되고 아니라면 그 때 값을 바꾸면 된다.
위와 차이점은 temp.insert 분기를 탔을 경우 find비용만큼 차이가 나게 된다는 점이다.
map에 클래스를 넣을 때, 자료가 매우 많아 메모리를 할당하는 것이 성공할 지 실패할 지 알 수 없을 때 다음과 같이 우선 두드려 보고 넣는 식으로 코드를 짜게 된다.
std::map<int, Foo*> temp;
temp.insert({ 1, new Foo });
...
{// 이렇게 하는 것은 중복된 Key를 삽입하는 경우가 많아지면, 무의미하게 new를 했다가 delete를 하는 부담이 생긴다.
Foo* pFoo = new Foo;
auto ret = temp.insert({ 1, pFoo });
if (!ret.second)
{
delete pFoo;
}
}
{// 그래서 다음과 같이 잘못 사용 하게 된다.
auto itr = temp.find(1);
if (itr == temp.end() )
{
temp.insert({ 1, new Foo });
}
}
2가지 방식을 해보는데,
1번 째는 docs를 참고한 우선 넣어보고 반환받은 pair를 이용해서 실패(중복)이라면 클래스를 delete 하게 된다.
2번 째는 우선 find하고 없으면 넣는다.
2번 째 방식이 1번 째 보단 나을 수 있으나 결국 가장 위에서 봤듯이 find, insert 비용을 중복으로 소모한다.
애초에 insert할 것이라면 find 할 필요 없이 아래처럼 사용한다.
nullptr를 넣고 키 값만 확인한 후에 true이면 그 때 할당해주면 된다.
auto ret = temp.insert({ 1, nullptr });
if (ret.second)
{
ret.first->second = new Foo;
}
'프로그래밍 > C++' 카테고리의 다른 글
C++/STL/Vector 동작 원리 (0) | 2022.01.31 |
---|---|
C++/캐스팅(Casting) (0) | 2022.01.29 |
C++/클래스 사이의 타입 변환 (0) | 2022.01.29 |
C++/malloc(free) vs new(delete) (0) | 2022.01.28 |
C++/메모리 구조 (0) | 2022.01.28 |