The way it works with std::map is that, if the key doesn't exist, the map class will insert a default value and then return an lvalue (an assignable reference to the value associated with the key), so it can be assigned a new value.
So, in the following code sample, assuming map is empty, this will insert 10 into the map and associate it with a value of 3.
map[10] = 3;
With your custom map class, operator[] should first check if the Key k exists, and if not, insert a new key/value pair (using the default constructor of typename Val) into the map. You can then return a reference to the Value associated with the new key, so the user can assign a value to it. Note that this means that Val must be Assignable and have a default constructor.
This allows operator[] to be used both for insertion and lookup. You should also overload a const version of operator[], which of course only supports lookup.
Edit: I now noticed in your code that you are returning a pointer. If you want to use the insert/lookup paradigm for operator[] used by std::map, it makes more sense to return a reference. Returning a pointer gives you the advantage that you can examine the return value of operator[] for NULL to check if the key doesn't exist, but again, if you want operator[] to provide both lookup and insert functionality, a reference would be the way to go here.