-1

I had trouble adding the foo object into the map myFoos until I found this answer which states that a default constructor is required.

When adding the object to the map, I was expecting it to be simply copied and put in place, however, what really happens is a default construction, an assignment and a copy.

Can someone explain this behaviour?

#include <map>

using namespace::std;

class Foo {
public:
  Foo() { }; // Default
  Foo(int id) : _id(id) { }; // Main
  Foo(const Foo& other) { }; // Copy
  Foo operator= (const Foo& other) { _id = other._id; return *this; } // Assign
  int getID() { return _id; }
private:
  int _id;
};

int main()
{
  map<int,Foo> myFoos;
  Foo foo(123);      // Main
  myFoos[123] = foo; // Default, Assign, Copy
}

Edit: I originally had no assignment happening in the function body of the assignment operator and some answers are correctly pointing that out. I modified the code accordingly.

Community
  • 1
  • 1
symphonic
  • 165
  • 2
  • 8
  • It will be in any documentation you find for `operator[]`. – chris Aug 06 '15 at 12:26
  • 1
    You've forgotten to do anything inside your `= operator` code. Set the id from the id of other at a minimum,or better yet, use the `copy and swap` idiom, as detailed here: http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom – enhzflep Aug 06 '15 at 12:40

2 Answers2

4

Before any assignments and copies can be done, the code myFoos[123] needs to create a Foo to insert into the map for the key 123. That value is then copied or moved into the map and then returned to you for further manipulation.

The index operator returns a reference to the element in the map, if it doesn't exist, it creates it and inserts it for you. If it does already exist, it just returns a reference to that already pre-existent one.

See std::map::operator[].

T& operator[]( Key&& key );

Returns a reference to the value that is mapped to a key equivalent to key, performing an insertion if such key does not already exist.

If an insertion is performed, the mapped value is value-initialized (default-constructed for class types, zero-initialized otherwise) and a reference to it is returned.


int id = myFoos[123].getID(); // returns 0 instead of 123

The 0 here is because the class is not yet fully implemented (default and copy constructor, and assignment operator), so the id is as initialised in the default constructor (in this case 0).

Community
  • 1
  • 1
Niall
  • 30,036
  • 10
  • 99
  • 142
3

operator[] initializes the element for the specified key using the default constructor, and returns a reference to it.

Your assignment operator omits (intentionally or otherwise) the assignment

_id = other._id.

Thus, in

myFoos[123] = foo;

the default _id=0 is not replaced by foo._id.

peterchen
  • 40,917
  • 20
  • 104
  • 186
  • I see. I defined the assignment operator in order to see when it gets called (I had it write it out) and so I messed up the actual assignment. My bad. Thank you for pointing it out. – symphonic Aug 06 '15 at 12:40