C ++ 17 std::map
은 두 가지 새로운 삽입 방법을 제공 하기 때문에 sp2danny 의 주석 에서도 언급했듯이 insert_or_assign()
및 .try_emplace()
insert_or_assign()
기본적으로은 insert_or_assign()
의 "개선 된"버전입니다 operator[]
. 대조적으로 operator[]
, insert_or_assign()
기본 작도 될지도의 값 유형을 필요로하지 않습니다. 예를 들어, 다음 코드는 MyClass
기본 생성자가 없기 때문에 컴파일 되지 않습니다.
class MyClass {
public:
MyClass(int i) : m_i(i) {};
int m_i;
};
int main() {
std::map<int, MyClass> myMap;
// VS2017: "C2512: 'MyClass::MyClass' : no appropriate default constructor available"
// Coliru: "error: no matching function for call to 'MyClass::MyClass()"
myMap[0] = MyClass(1);
return 0;
}
그러나 myMap[0] = MyClass(1);
다음 줄로 바꾸면 코드가 컴파일되고 의도 한대로 삽입이 수행됩니다.
myMap.insert_or_assign(0, MyClass(1));
또한, 유사 insert()
, insert_or_assign()
반환합니다 pair<iterator, bool>
. 부울 값은 true
삽입이 발생한 false
경우와 할당이 완료된 경우입니다. 반복기는 삽입 또는 업데이트 된 요소를 가리 킵니다.
try_emplace()
위와 유사하게의 try_emplace()
"개선"입니다 emplace()
. 대조적으로하는 emplace()
, try_emplace()
삽입은 이미 맵에 존재하는 키 때문에 실패 할 경우 인수를 수정하지 않습니다. 예를 들어 다음 코드는 맵에 이미 저장된 키로 요소를 배치하려고합니다 (* 참조).
int main() {
std::map<int, std::unique_ptr<MyClass>> myMap2;
myMap2.emplace(0, std::make_unique<MyClass>(1));
auto pMyObj = std::make_unique<MyClass>(2);
auto [it, b] = myMap2.emplace(0, std::move(pMyObj)); // *
if (!b)
std::cout << "pMyObj was not inserted" << std::endl;
if (pMyObj == nullptr)
std::cout << "pMyObj was modified anyway" << std::endl;
else
std::cout << "pMyObj.m_i = " << pMyObj->m_i << std::endl;
return 0;
}
출력 (최소 VS2017 및 Coliru의 경우) :
pMyObj가 삽입되지 않았습니다.
pMyObj가 어쨌든 수정되었습니다.
보시다시피는 pMyObj
더 이상 원래 개체를 가리 키지 않습니다. 그러나 auto [it, b] = myMap2.emplace(0, std::move(pMyObj));
다음 코드로 대체하면 pMyObj
변경되지 않은 상태로 유지 되므로 출력이 다르게 보입니다 .
auto [it, b] = myMap2.try_emplace(0, std::move(pMyObj));
산출:
pMyObj가 삽입되지 않았습니다.
pMyObj pMyObj.m_i = 2
Coliru의 코드
참고 :이 답변에 맞게 설명을 가능한 한 짧고 간단하게 유지하려고했습니다. 보다 정확하고 포괄적 인 설명 을 위해 Fluent C ++ 에 대한 이 기사 를 읽는 것이 좋습니다 .