Are pointers allowed as keys in ordered STL containers?
There's this other question asking about how comparing pointers is supposed to be interpreted wrt the C++ Std.
So I was wondering what the C++ Std has to say about using pointers as keys in ordered standard library (STL) containers -- i.e. is one allowed to have
std::map<T1*, T2>
and is this due to the specification of std::less
or builtin operator 开发者_运维问答<
?
Yes, because it uses std::less
, which is required to result in a total order even if <
doesn't. (<
would be allowed to treat different pointers from distinct sequences as equal, which would result in an odd behaviour of map
etc if you insert pointers from different sequences).
I'd like to add another reason to not do this. If you are using pointers in this way, and if you happen to have a bug that depends on the ordering of the elements of a container, then it will be very difficult to find. Even if your program seems to be completely deterministic, it will not be. The order of the elements in a container depends on the algorithm the memory allocator uses, which is completely out of your control. If you run the same example muliple times without restarting your program, some may fail and others succeed.
This is the voice of bitter experience. I did this with a debugger project once, where I had containers filled with C++ symbols. When I needed to sort the symbols, I ended up with symbols which are different, but which have the same name (think overloaded functions) and which were identical in all other respect. So, in this case I compared them as a last resort by the address of the symbol object. I ran into several bugs which were apparently non-deterministic, where the non-determinism was caused by just this phenomenon. Sometimes it took more than 10 or 15 attempts to reproduce the problems. I eventually took the time to eliminate sorting by addresses, and that saved me a lot of trouble over the longer term.
With that said, I won't say I haven't done this recently. But every time I do it I feel like it's a mistake.
"They may valid but don't" is the answer I would give.
Obviously there is the issue of comparability that you raise, but the reason you don't want to is because of the lack of reference management on "vanilla" pointers. It's very easy for the object to be deleted without it being removed from the container, resulting in an invalid pointer and an access violation next time you go to access it.
Yes. Pointers are comparable via operator<().
If the pointers do not point to the elements of the same array or elements within the same object the c++ standard says the behavior is unspecified [expr.rel].
The standard says unspecified behavior means it's implementation defined [defns.unspecified].
If your compiler guaranties a strict weak order of pointers you can use any pointer with associative containers.
Most compilers do pointer comparison by comparing the memory addresses. On most architectures this comparison forms a strict weak order.
Therefore it's safe to use pointers as keys.
精彩评论