mercredi 1 mars 2017

std::map operator< pointer address compare vs pointer value compare

I was investigating how map handles custom types and I came across some odd behavior.

I created a custom type ´ComplexType´ that has 1 member, a pointer to an int. I first compared using the value of this int, which gave the expected behavior.

#include <iostream>
#include <map>

struct ComplexType
{
    ComplexType(int i): index(new int(i)){
    };
    ComplexType(const ComplexType& cT): index(new int(*cT.index)){
    }
    ~ComplexType(){
        if(index){
            delete index;
        }
    }
    bool operator<(const ComplexType cT) const
    {
        return *index < *cT.index;
    }
    int* index;

};

int main(){
    int pi[] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 8};
    std::map< ComplexType , int  > container;
    for(int i = 0; i < 12; ++i){
        container[ComplexType(i)] = pi[i];
    }
    std::cout << "Loop map, size: " << container.size() <<  std::endl;
    for(auto it = container.begin();it != container.end(); it++){
        std::cout << "Show index map, size: " << container.size() <<  std::endl;
        std::cout << *it->first.index << std::endl;
    }
    return 0;
}

With the output:

Loop map, size: 12
Show index map, size: 12
0
Show index map, size: 12
1
Show index map, size: 12
2
Show index map, size: 12
3
Show index map, size: 12
4
Show index map, size: 12
5
Show index map, size: 12
6
Show index map, size: 12
7
Show index map, size: 12
8
Show index map, size: 12
9
Show index map, size: 12
10
Show index map, size: 12
11

Now I changed my compare function to compare on the address of the pointer.

#include <iostream>
#include <map>

struct ComplexType
{
    ComplexType(int i): index(new int(i)){
    };
    ComplexType(const ComplexType& cT): index(new int(*cT.index)){
    }
    ~ComplexType(){
        if(index){
            delete index;
        }
    }
    bool operator<(const ComplexType cT) const
    {
        return index < cT.index;
    }
    int* index;

};

int main(){
    int pi[] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 8};
    std::map< ComplexType , int  > container;
    for(int i = 0; i < 12; ++i){
        container[ComplexType(i)] = pi[i];
    }
    std::cout << "Loop map, size: " << container.size() <<  std::endl;
    for(auto it = container.begin();it != container.end(); it++){
        std::cout << "Show index map, size: " << container.size() <<  std::endl;
        std::cout << *it->first.index << std::endl;
    }
    return 0;
}

I expected this to result in a random order based on what addresses the pointer got on the heap. Instead I got the following:

Loop map, size: 12
Show index map, size: 12
1
Show index map, size: 12
0

I compiled using g++:

g++ (GCC) 5.3.0
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

\randomness map>g++ -std=c++11 -o mapConstructionComplexType mapConstructionComplexType.cpp

\randomness map>g++ -std=c++11 -o mapConstructionComplexTypePointerCmp mapConstructionComplexTypePointerCmp.cpp

Can anyone explain this odd behavior?

Aucun commentaire:

Enregistrer un commentaire