태그 보관물: stl

stl

STL 맵에서 map :: insert를 사용하는 것이 []보다 낫습니까? 방법에 대해 동료와 토론했습니다 . 나는

얼마 전에 저는 STL 맵에 값을 삽입하는 방법에 대해 동료와 토론했습니다 . 나는
map[key] = value;
그것이 자연스럽고 읽기 쉽기 때문에 선호했습니다.
map.insert(std::make_pair(key, value))

나는 방금 그에게 물었고 우리 중 어느 쪽도 insert가 더 나은 이유를 기억할 수는 없지만 그것이 스타일 선호가 아니라 효율성과 같은 기술적 이유가 있다고 확신합니다. SGI의 STL 참조는 단순히 “엄밀히 말하면이이 멤버 함수가 필요하지 않습니다. : 그것은 단지 편의를 위해 존재한다”라는

아무도 그 이유를 말해 줄 수 있습니까, 아니면 하나가 있다고 꿈꾸고 있습니까?



답변

당신이 쓸 때

map[key] = value;

이 같은 경우 알 수있는 방법은 없습니다 교체value 대한이 key, 또는 당신이 경우 생성 된 새로운를 key함께 value.

map::insert() 만 만들 것입니다 :

using std::cout; using std::endl;
typedef std::map<int, std::string> MyMap;
MyMap map;
// ...
std::pair<MyMap::iterator, bool> res = map.insert(MyMap::value_type(key,value));
if ( ! res.second ) {
    cout << "key " <<  key << " already exists "
         << " with value " << (res.first)->second << endl;
} else {
    cout << "created key " << key << " with value " << value << endl;
}

대부분의 내 앱에서는 일반적으로 생성 또는 교체 여부를 신경 쓰지 않으므로 더 읽기 쉽습니다 map[key] = value.


답변

맵에 이미 존재하는 키와 관련하여 두 가지 의미가 다릅니다. 그래서 그들은 실제로 직접 비교할 수 없습니다.

그러나 operator [] 버전은 기본적으로 값을 구성한 다음 할당하는 것이 필요하므로 복사 비용보다 비싸면 비용이 더 많이 듭니다. 때로는 기본 구성이 의미가 없으므로 operator [] 버전을 사용하는 것이 불가능합니다.


답변

주목해야 할 또 다른 사항 std::map:

myMap[nonExistingKey];지도 nonExistingKey에 기본값 으로 초기화 된 새 항목을 만듭니다 .

이것은 내가 그것을 처음 보았을 때 지옥에서 나에게 두려움을주었습니다. 예상하지 못했을 것입니다. 나에게는 그것이 get 작업처럼 보이며 나는 “부작용”을 기대하지 않았다. 취하다map.find()지도에서 나올 때 하십시오.


답변

기본 생성자의 성능 적중이 문제가되지 않으면 신을 사랑하기 위해 더 읽기 쉬운 버전으로 이동하십시오.

🙂


답변

insert 예외 안전의 관점에서 더 좋습니다.

이 표현 map[key] = value은 실제로 두 가지 연산입니다.

  1. map[key] -기본값으로지도 요소를 만듭니다.
  2. = value -해당 요소에 값을 복사합니다.

두 번째 단계에서 예외가 발생할 수 있습니다. 결과적으로 작업은 부분적으로 만 수행됩니다 (새 요소가 맵에 추가되었지만 해당 요소는로 초기화되지 않았습니다 value). 작업이 완료되지 않았지만 시스템 상태가 수정 된 상황을 “부작용”이있는 작업이라고합니다.

insert작업은 강력한 보증을 제공하므로 부작용이 없습니다 ( https://en.wikipedia.org/wiki/Exception_safety ). insert완전히 완료되었거나 맵을 수정되지 않은 상태로 둡니다.

http://www.cplusplus.com/reference/map/map/insert/ :

단일 요소를 삽입하는 경우 예외가 발생할 경우 컨테이너가 변경되지 않습니다 (강력 보장).


답변

응용 프로그램이 속도가 중요한 경우 [] 연산자를 사용하여 조언합니다. 원래 객체의 총 3 복사본을 생성하고 그중 2 개는 임시 객체이며 조만간 파괴됩니다.

그러나 insert ()에서 원래 오브젝트의 사본 4 개가 작성되고 그 중 3 개는 임시 오브젝트 (필수 “임시”일 필요는 없음)이며 파괴됩니다.

1. 한 개의 객체 메모리 할당 2. 한 개의 추가 생성자 호출 3. 한 개의 추가 소멸자 호출 4. 한 개의 개체 메모리 할당 해제

객체가 크면 생성자가 일반적이며 소멸자는 많은 리소스 확보를 수행합니다. 가독성에 관해서는, 나는 둘 다 공평하다고 생각합니다.

같은 질문이 내 마음에 들었지만 가독성이 아니라 속도입니다. 여기 내가 언급 한 요점에 대해 알게 된 샘플 코드가 있습니다.

class Sample
{
    static int _noOfObjects;

    int _objectNo;
public:
    Sample() :
        _objectNo( _noOfObjects++ )
    {
        std::cout<<"Inside default constructor of object "<<_objectNo<<std::endl;
    }

    Sample( const Sample& sample) :
    _objectNo( _noOfObjects++ )
    {
        std::cout<<"Inside copy constructor of object "<<_objectNo<<std::endl;
    }

    ~Sample()
    {
        std::cout<<"Destroying object "<<_objectNo<<std::endl;
    }
};
int Sample::_noOfObjects = 0;


int main(int argc, char* argv[])
{
    Sample sample;
    std::map<int,Sample> map;

    map.insert( std::make_pair<int,Sample>( 1, sample) );
    //map[1] = sample;
    return 0;
}



답변

이제 c ++ 11에서 STL 맵에 쌍을 삽입하는 가장 좋은 방법은 다음과 같습니다.

typedef std::map<int, std::string> MyMap;
MyMap map;

auto& result = map.emplace(3,"Hello");

결과 와 쌍 될 것입니다 :

  • 첫 번째 요소 (result.first)는 삽입 된 쌍을 가리 키거나 키가 이미 존재하는 경우이 키를 가진 쌍을 가리 킵니다.

  • 두 번째 요소 (result.second), 삽입이 정확하거나 거짓이면 무언가 잘못되었습니다.

추신 : 주문에 대해 사건이 없다면 std :: unordered_map;)

감사!