arrays first vs. vectors first

Pages: 12
I am constantly surprised to see people who are supposedly learning C++ attempting to solve problems using arrays and pointers while being completely unfamiliar with vectors (or other containers) and iterators (or even with strings! Although I think I'm starting to see more student code that uses C++ strings for characters and C arrays for everything else).

I think arrays are so much disconnected from the rest of C++ (despite C++11's special versions of swap(), begin(), end(), and unique_ptr), that learning them before any normal container is a serious setback. Nobody needs to deal with the compatibility compromises made between B and C in 1972 when learning C++ in 2012.

Textbooks seem to agree:

Good old Accelerated C++ (2000)
Chapter 3.2.1 "A vector holds a sequence of values of a given type"
Chapter 10.1 "An array is a kind of container, similar to a vector but less powerful."


Equally old Thinking in C++ (2000)
Chapter 2 "It’s so useful that the most basic of the standard containers, the vector, is introduced in this early chapter and used throughout the book."
Chapter 3 "Arrays are a kind of composite type because they allow you to clump a lot of variables together, one right after the other"


Stroustrup's favorite Programming Principles and Practice (2006)
Chapter 4.6 "Here we will start with one of the simplest, and arguably the most useful, ways of storing data: a vector"
Chapter 17.4.1 "The new operator can allocate individual elements or sequences (arrays) or elements."
Chapter 18.5 "For a while, we have used array to refer to a sequence of objects allocated on the free store. We can also allocate arrays elsewhere as named variables."


Shiny new C++ Primer (2012)
Chapter 3.3. "A vector is a collection of objects, all of which have the same type"
Chapter 3.5. "An array is a data structure that is similar to the library vector type"


Opinions? Arguments to the contrary?
I can do nothing but agree.

I wonder how long it will it be before we actually see "learners" post code using std::array.
The problem is with the way C++ is taught in academia. That is... poorly. Often times by teachers who know much less about the language than they should.

So I agree.


Then again, the common counter-argument to this is that "it's better to learn from the bottom up". That is, you should learn lower level concepts first, so that you can truly understand how higher level containers work and use them effectively.

Personally I don't agree with that approach and have had great success learning top-down. But in a way it's an equally valid approach.
I know how to use vectors, but I prefer to dynamically allocate on my own when I don't need the functionality. Maybe it's a bad habit.

When a higher level feature doesn't have any advantages for a given use, I prefer to use the lower level way.

Sometimes I feel like C++ programmers are a little over paranoid, or protective, or what have you.

If your using vector, you using a dynamically allocated array anyways. You just don't see it.

I'm sure if I ever work on a larger collaborative project, I'll use vector all the time; to make everyone comfortable, and to be extra careful I, or someone, doesn't accidentally mess things up and cause a memory leak.

Last edited on
IMO, if you think phrases like "arrays are like vectors" aren't complete nonsense, you probably don't need C++, since the code you produce will be no faster than if you had written it in a higher level language. It'll just take you longer.

I think arrays are so much disconnected from the rest of C++ (despite C++11's special versions of swap(), begin(), end(), and unique_ptr), that learning them before any normal container is a serious setback.
I don't really understand this line of thought, considering arrays are built-in while STL containers are not. I would go so far as to say they're positively elegant when put in context with pointers and pointer arithmetic.
How are they disconnected?
I don't really understand this line of thought, considering arrays are built-in while STL containers are not.

That's an important point. Being built-in makes a big difference in "feel", I believe. This is why D has built-in dynamic arrays and built-in maps (which they call "associative arrays").

To fix this education problem, we should write articles about proficient C++ style.
Last edited on
helios wrote:
f you think phrases like "arrays are like vectors" aren't complete nonsense, you probably don't need C++, since the code you produce will be no faster than if you had written it in a higher level language.

std::sort() over a vector is many times faster than qsort() over an array (granted, it's not array's fault, it's the function pointers that murder performance in C).

arrays are built-in while STL containers are not

The first program people learn in either language relies on the library components for I/O. Unless you're writing a parser for C++, studying the library cannot be an afterthought.

How are they disconnected?

non-copyable/movable/returnable, unlike the rest of the containers (unless wrapped in structs)

confusing to the beginners due to array-to-pointer conversion (which other containers don't have), so much so that people equate them with pointers.

size-unaware (dynamic array only), which means the programmers have to drag along another piece of information everywhere they take the array, which leads to "pointer + size" style of programming, while in C++ you would rather have "pointer + pointer"

size is part of the type (non-dynamic arrays only), and can't be accessed the same way as the size of other containers.

allocator-unaware (dynamic array only), that's a deal-breaker for me in particular (we don't use new, we have too many different kinds of memory -- how I have to drag around pointer, size, and the allocator object? I might as well write my own vector)

what am I saying, dynamic arrays aren't even accessible and have no names, can't be referenced, and the language bends over backwards with special rules for the pointers to their first elements.

(until C++11 for non-dynamic) non-swappable

(until C++11 for non-dynamic) unusable in generic programming because there was no common way to obtain iterators or value type from arrays that would also work with the rest of the containers.
Last edited on
Gotta say I fully agree with Cubbi here. The first book I read while learning taught C++ pretty much as C with I/O streams and I'd say that negatively effected me. Even still I find myself using C style arrays and having the issue of passing size a long with it when I could have just used vector and made life easier.

Though having one more include can also be kind of irritating. I don't know about the rest of you, but I hate having a long list of includes in any given file.
std::vector is slower, array is uglier, so hooray for std::array. Is there anything else that needs to be said in this thread?
std::sort() over a vector is many times faster than qsort() over an array (granted, it's not array's fault, it's the function pointers that murder performance in C).
And?

non-copyable/movable/returnable, unlike the rest of the containers (unless wrapped in structs)

size is part of the type (non-dynamic arrays only), and can't be accessed the same way as the size of other containers.
Well, they aren't containers. This is like complaining that arrays cannot be added, unlike bignums that use arrays internally.

size-unaware (dynamic array only), which means the programmers have to drag along another piece of information everywhere they take the array, which leads to "pointer + size" style of programming, while in C++ you would rather have "pointer + pointer"

allocator-unaware (dynamic array only), that's a deal-breaker for me in particular (we don't use new, we have too many different kinds of memory -- how I have to drag around pointer, size, and the allocator object? I might as well write my own vector)

(until C++11 for non-dynamic) non-swappable

(until C++11 for non-dynamic) unusable in generic programming because there was no common way to obtain iterators or value type from arrays that would also work with the rest of the containers.
You seem to be answering an entirely different question. This sounds like an answer to "how are arrays not powerful?"

what am I saying, dynamic arrays aren't even accessible and have no names, can't be referenced, and the language bends over backwards with special rules for the pointers to their first elements.
Well, first of all, this is not what you're saying, because I don't see anything in your post that implies any of these things, outside of this sentence.
Second, can you clarify these points?
* Not accessible.
* Not referenceable.
* Special rules.
And?

Just responding to your idea that those who think "array is similar to vector" is the normal way to think about it aren't interesting in performance. I say they start off with faster code. But that is indeed a side track, the thread is about education trends.

This sounds like an answer to "how are arrays not powerful?"

No, I am talking about how they are disconnected from the rest of C++. The rest of the language and the library works together, more or less uniformly, except the arrays.

can you clarify these points?
* Not accessible.
* Not referenceable.
* Special rules.

Say you have a function that prints a container,
1
2
3
4
5
6
7
template<typename C>
void print(const C& container)
{
    for(const auto& element: container)
        std::cout << element << ' ';
    std::cout << '\n';
}

This function can be used with a non-dynamic array (since c++11)

1
2
int m[] = {1,2,3};
print(m);

but it cannot be used with a new[]'d array:

1
2
3
int* p = new int[3]{1,2,3};
print(???); // this array is not accessible!
delete[] p;


By special rules I mean the double-duty of the pointer to the first element of the dynamic array: it's both the begin iterator, and (through special relationship known to delete[] but not to delete, made doubly special for char[] arrays) the dynamic lifetime handler.
Just responding to your idea that those who think "array is similar to vector" is the normal way to think about it aren't interesting in performance. I say they start off with faster code.
Faster relative to, in this example, code that uses qsort(). Using arrays doesn't force you to use qsort() to sort them.

No, I am talking about how they are disconnected from the rest of C++. The rest of the language and the library works together, more or less uniformly, except the arrays.
What would you say would make them more uniform with the rest?

Say you have a function that prints a container. This function can be used with a non-dynamic array (since c++11) but it cannot be used with a new[]'d array
If you write a function in a way that isn't compatible with arrays, of course you're going to have problems if you try to use arrays with it. This is like complaining that a function over the integers behaves like a function over the integers even when you pass a float.

If you want full genericity, just do it the STL way:
1
2
3
4
5
6
template<typename Iterator>
void print(Iterator begin,Iterator end){
    for(;begin!=end;++begin)
        std::cout << *begin << ' ';
    std::cout << '\n';
}
On the point of teaching C++, I think it's a huge task. The language is one thing, it's just got more and more complicated, and then there's the standard library.

You have to start somewhere, you can't expect students to start writing expert code. So what if they use arrays?
They can teach Java just fine. I'd say that has a much larger built in library than C++ does. Why should it be any different for C++?
It's different because you don't need to understand how Java libraries work to use them effectively, whereas you do in C and C++.
How do you figure? Java and C++ have the same types of containers that operate in almost the same way. Both have iterators, both have file I/O classes.

I'd say you're defining effectively here different for Java and C++. If we define effectively as in proper use in the proper situations, they're the same. The Java equivalents of C++ STL classes work in a pretty similar manner.

To say you need to understand the deep workings of a library to use it is not a language fault. That's a library fault. All a programmer using a library should care about is the outside interface.
I don't know about Java, but understanding how the platform, libraries and language works, and thus how you write your code, can definitely have a significant effect on the performance of C#. I imagine the same applies to Java, and it certainly applies to C++.
Well see I wouldn't call that just effective at that point. This is saying if someone doesn't understand the intricacies of what a library is doing underneath, then you are an ineffective programmer. This just isn't true. Sure, knowing exactly how a library is implement can't hurt your ability, but that's not the line of being effective/ineffective.
If you don't understand that certain containers are implemented with some kind of tree structure, or others with linear structures, you'll have to learn their characteristics by rote, and that can't be good.
But that's just computation theory. People should either 1) know this already or, 2) the library won't expect you to know and will interface in such a manner.
Pages: 12