Andy Koenig is the expert’s expert, and I rarely disagree with him. And, well, when I do disagree I’m invariably wrong… but there’s a first time for everything, so I’ll take my chances one more time.
I completely agree with the overall sentiment of Andy’s blog entry today:
I spend a fair amount of time reading (and sometimes responding to) questions in the C++ newsgroups. Every once in a while, someone asks a question that makes me cringe.
What makes a question cringe-worthy?
Usually it is a question that implies that the person asking it is trying to do something inappropriate.
Asking how to violate programming-language abstractions is similar: If you have to ask, you probably shouldn’t be doing it.
Amen! Bravo! Absolutely correct. Great stuff. Except that the example in question isn’t violating an abstraction:
For example, I just saw one such question: Are the elements of a std::vector contiguous? Here is why that question made me cringe.
Every C++ container is part of an abstraction that includes several companion iterators. The normal way of accessing a container’s elements is through such an iterator.
I can think of only one reason why one should care whether the elements of a vector are in continuous memory, and that is if you intend to use pointers, rather than iterators, to access those elements. Doing so, of course, violates the abstraction.
There is nothing wrong per se with violating abstractions: As Robert Dewar told me more years ago than I care to remember, some programs are poorly designed on purpose. However, there is something wrong with violating abstractions when you know so little of the data structures used to implement those abstractions that you have to ask strangers on Usenet about your proposed violation. To put it more bluntly: If you have to ask whether vector elements are contiguous, you probably should not be trying to make use of that knowledge.
The reason this analysis isn’t quite fair is that contiguity is in fact part of the vector abstraction. It’s so important, in fact, that when it was discovered that the C++98 standard didn’t completely guarantee contiguity, the C++03 standard was amended to explicitly add the guarantee.
Why is it so important that vectors be contiguous? Because that’s what you need to guarantee that a vector is layout-compatible with a C array, and therefore we have no reason not to use vector as a superior and type-safe alternative to arrays even when we need to exchange data with C code. So vector is our gateway to other languages and most operating systems features, whose lingua franca is the venerable C array.
And it’s not just vector: The TR1 and C++0x std::array, which implements fixed-size arrays, is also guaranteed to be contiguous for the same reasons. (std::array is available in Boost and, ahem, the VC++ TR1 implementation we shipped today.)
So why do people continually ask whether the elements of a std::vector (or std::array) are stored contiguously? The most likely reason is that they want to know if they can cough up pointers to the internals to share the data, either to read or to write, with other code that deals in C arrays. That’s a valid use, and one important enough to guarantee in the standard.