frob said:
Don't prematurely optimize. Use it if you need it. Don't try to make things faster until you've measured and you know you actually need to.
This being said, don't intentionally choose approaches that you know up front will be slower. I've seen “no premature optimization” used to justify baffling and unnecessary choices of things that are inherently slow when something that was inherently faster was every bit as ergonomic and sometimes even more so. Don't use a linked list when an array or vector is ergonomic to your problem, as it will almost always be slower. Don't use a hashmap for a container that will never be more than four elements in size and is indexed by a contiguous enum - you know up front that hashing the elements has a cost and many hashmap implementations involve heap allocations and cache misses. Don't use a resizeable vector for a container that will always be exactly four elements in size - you don't need the dynamic resizing and so paying the cost for that is not necessary. People really do this; I have called out every one of those examples in actual, production code reviews.
“You ain't gonna need it” applies to features that impact performance, not just architectural elements!
“No premature optimization” shouldn't be taken to mean “don't think about performance at all in your initial choices" and it enrages me that it is commonly misunderstood to mean that. It should not mean “use the slowest container available with the interface you want.” I'm tired of having to reject people's work in code reviews because they think std::unordered_map is the only data structure and they don't want to put any thought into how the machine will actually solve their problem at all.