std::map Members refering all to one address

117 views Asked by At

I am using std::map, similar to the implemtentation in webrtc (see here). My Map is defined like that:

typedef std::map <std::string, BaseOption*> OptionMap;

And the BaseOption (Option) is defined:

class BaseOption {
public:
    virtual ~BaseOption() {}
};

template<typename T>
class Option : public BaseOption {
public:
    explicit Option(T* v) {value = v;}
    ~Option() { delete value; }
    T* value;
};

The Set-Member:

template<typename T>
void ClassFoo::Set(OptionIdentifier option_, T* value) {

    BaseOption*& option_member = options_[option];
    delete option_member;
    option_member = new Option<T>(value);

}

I call fill the map from a class-member called put_into_map (just a quick-and-dirty implementation to test my class):

void ClassFoo::put_into_map(){

    int tempval = 8000;

    this->Set<int>("IeAIf", &tempval);
    this->Set<int>("LcE8V", &tempval);

    tempval = 16000;
    this->Set<int>("RVn1C", &tempval);
    this->Set<int>("XINa2", &tempval);

    tempval = 1;
    this->Set<int>("st6Vz", &tempval);

    this->printAll<int>();
}

And used from main:

int main(){
    ClassFoo foo_object = new ClassFoo();
    foo_object->put_into_map();

    return 0;
}

The printAll works like:

template<typename T>
void ConfTool::printAll(){

    std::cout << "#Elem in Map " << this->options_.size() << std::endl;

    OptionMap::const_iterator it;
    for (it = options_.begin(); it != options_.end(); ++it)
    {
        std::cout << "Arg: " << it->first <<    "  Value: \t" << static_cast<Option<T>*>(it->second)->value   << std::endl;
    }
}

Inserting different stuff into the map, and dumping it (or useing it), all Options have the same value. Also dumping the addresses behinde these values, the same spaces gets shown (inserted some random Data):

Arg: IeAIf  Value:  0x7fffc49980cc
Arg: LcE8V  Value:  0x7fffc49980cc
Arg: RVn1C  Value:  0x7fffc49980cc
Arg: XINa2  Value:  0x7fffc49980cc
Arg: st6Vz  Value:  0x7fffc49980cc

I assume that I failed to design the Set-Member in a correct way.

1

There are 1 answers

1
PaulMcKenzie On BEST ANSWER

You need to rethink your design. You get the same pointer in the output due to you storing the same pointer (&tempval) in Option::value.

If you printed it->second, you will see that this particular pointer is different. But when you get value, i.e. (it->second)->value, you wind up with &tempVal, exactly as how you coded it.

In other words, the program is doing exactly as described -- you stored a pointer, you will get the pointer. Nothing in your design "extracts" the value that is located at the pointer and places it in the new Option instance.

Here is a minimal example of your code showing this: http://ideone.com/jn5GtU

Note that the address that is held by it->second is changing, but it->second->value does not change. It also happens to be the &tempVal.