liveBook · Manning

Array

As explained in 100 C++ Mistakes and How to Avoid Them

An array is a fixed-layout sequence of elements accessed by position through an index.

An array is a sequence of elements addressed through one name and distinguished by an index. It is familiar and sometimes efficient, but it often creates correctness and maintenance problems when used as a general-purpose container. section 5.10 section 6.8

Treat arrays cautiously when:

  • The element count is unknown or arbitrary at compile time. Static arrays can waste space when oversized or cause crashes when undersized. section 5.10
  • Elements lack meaningful default values. Creating an array of objects invokes a default constructor for every element, potentially violating the class invariant. section 7.8
  • Functions receive raw arrays. Callers must pass the element count separately, creating opportunities for missed data or access beyond the end. section 6.8
  • Elements are added, removed, or invalidated. Manual resizing, copying, reference changes, and validity markers spread container knowledge through the code. section 5.10

Prefer a vector for growing collections

A raw array requires a chosen size and can force meaningless initialization: Person people[3]. A vector instead accepts constructed objects with push_back and can reserve computed capacity without requiring a default constructor. Iterator-based functions also receive the container rather than a pointer-plus-size pair. section 5.10 section 6.8

Listing 5.22 Static arrays force using a default constructor
struct Person {
    std::string name;
    int age;
    Person(const std::string& n, int a) : name(n), age(a) {}
    Person() : name("", 0) {}
};
 
int main() {
    Person people[3];                                       #1
    Person suzy("Susan", 25);
    people[0] = suzy;
    Person anna("Annette", 32);
    people[2] = anna;
    std::cout << people[1].name << '\n';
 
    int count = 5;  // assume this is computed
    Person* others = new Person[count];                     #2
    return 0;
}

Inspect the static and dynamically allocated Person arrays to see how array creation forces default construction. section 5.10

Listing 5.23 Using a vector to replace awkward arrays
struct Person {
    std::string name;
    int age;
    Person(const std::string& n, int a) : name(n), age(a) {}
};
 
int main() {
    std::vector<Person> people;
    Person suzy("Susan", 25);
    people.push_back(suzy);
    Person anna("Annette", 32);
    people.push_back(anna);
    std::cout << people[people.size()-1].name << '\n';
 
    int count = 5;  // assume this is computed
    std::vector<Person> others;
    others.reserve(count);
    return 0;
}

Compare the vector replacement, including push_back for meaningful objects and reserve for computed capacity. section 5.10

How 100 C++ Mistakes and How to Avoid Them covers it

How deep it goes
Explains array sizing, default construction, resizing, invalid elements, and indexing, but defers lower-level implementation details.
Examples
Uses Person arrays, vector replacements, raw-array summation, and iterator-based summation over vector and set containers.
What it assumes
Assumes familiarity with indexed sequences and basic C++ objects while teaching why default construction and separate size tracking are risky.
What you can do after
Evaluate array usage and replace many collections with vectors or iterator-based interfaces when size, construction, or validity is difficult to manage.
How it connects
Connects arrays with vectors, iterators, default constructors, class invariants, dynamic arrays, and standard library containers.

Also explained in

Compare how 40 books explain array →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of 100 C++ Mistakes and How to Avoid Them. The section links point to the parts of the book it draws on.