Concepts / Container Operations: push_back() and erase()

Container Operations: push_back() and erase()

push_back() is called on the container and appends a new element at the end.

  • Programming

A Task That Seems to Need a Different Size

Suppose you have a list of numbers and you want to replace every occurrence of one value with another. Or suppose you want to sort the numbers into order. Neither task obviously requires a different number of elements. Replacing a value leaves the count alone, and sorting rearranges the values that are already there. Now suppose instead that you want to add a new number to the end of the list, or remove a number from the middle. These tasks clearly change how many elements are stored. The question this article answers is how a program tells these two kinds of work apart, and which operation is responsible for each.

The source material frames the problem with a simple observation: it is tempting to think that an algorithm can grow or shrink a container whenever its task seems to call for it. The answer is that changing what is stored and changing how many elements are stored are different jobs. The key question is whether an operation works with a sequence of elements or with the container that holds them.

What do you think happens?

Start with v holding the values 1, 2, 3. You call replace(v.begin(), v.end(), 2, 9). What is v.size() afterward?

  • 2

  • 3

  • 4

  • It depends on the value 9

Reveal answer
Answer:

3

replace() changes the value 2 to 9 in an existing position. It does not add or remove any element, so the size stays at 3. The array now holds 1, 9, 3.

Values Versus the Container

Two different kinds of work happen to a container. The first kind changes the values stored in positions that already exist. The second kind changes how many positions exist. Algorithms such as replace() and sort() belong to the first kind. The summary of the source material states that these algorithms can change element values without changing the number of elements.

The source explains that the distinction matters whenever an operation's result seems to require a different number of elements. If the task is to change values, an algorithm such as replace() or sort() may be suitable. If the task is to add or remove elements, the operation must also have a way to act on the container itself.

Index 01Index 19Index 23
When replace() changes the value 2 to 9 in a container of three slots, only the slot at index 1 is written. The container still has three slots before and after.

Read the diagram as a list of slots. The replace() operation finds the slot that holds the value 2 and writes 9 into that same slot. The other slots are not touched, and no slot is added or removed. This is why the number of slots is the same before and after. The algorithm changed what is stored, not how much is stored.

Why a Sequence Cannot Resize Its Container

An algorithm such as replace() or sort() receives a sequence, usually described by a range of positions from a starting point up to an ending point. A sequence does not identify the container that holds its elements. The algorithm can read and write the positions it has been given, but it has no handle on the container object itself. Without that handle, the algorithm has no way to add a new slot at the end or to close a gap in the middle.

The source describes this as a missing connection. Think of the back_inserter as the connection between an algorithm and the container that should grow. Without a way to refer to the container, the sequence alone does not tell the algorithm where added elements belong. The sequence tells the algorithm which values to read and where to write, but not where a new element should go once the existing positions are full.

Tracing replace() on a Vector

Worked example

Changing a value without changing the size

A container named v holds the values 1, 2, 3. Use replace() to change the value 2 to 9, then confirm whether the size of the container has changed.

  1. 1
    Start with the initial state

    The container holds three elements: 1 at index 0, 2 at index 1, and 3 at index 2. Its size is 3.

  2. 2
    Pass a sequence to replace()

    The algorithm receives the range from the first position to the position just past the last one. It searches that range for the value 2.

  3. 3
    Write the new value into the matching position

    The value 2 is found at index 1, so that position is overwritten with 9. No other position is written.

  4. 4
    Check the size

    No element was added or removed. The container still has three positions, now holding 1, 9, and 3.

Result

The values changed, but the size stayed at 3. This is the behavior the source attributes to algorithms such as replace() that change element values without changing the number of elements.

python
Output (expected)
3
1 9 3 
Notes on the code
  • v.begin() and v.end() form the sequence passed to the algorithm.
  • replace() writes 9 into the one matching position.
  • The size printed afterward is still 3.

The example uses the C++ standard library names for these operations. The same idea holds in any setting where an algorithm is given a range of positions: the operation rewrites values inside that range and leaves the number of positions to whoever owns the container.

Growing and Shrinking the Container Directly

When the task is to add or remove elements, the operation must act on the container itself. The source names two direct container operations for this purpose: push_back() for adding an element and erase() for removing one. Each is called on the container, so it has the handle that the sequence alone lacks.

Because these operations change the container, they change how many elements it holds. This is the second kind of work described earlier. The rule of thumb from the source is simple: use direct container operations such as push_back() or erase() when adding or removing elements directly.

Connecting Algorithms with back_inserter

Sometimes an algorithm does produce output that must be stored in a container that grows. The source gives the rule: use a back_inserter to connect an algorithm to a container when adding elements. The back_inserter supplies the missing link. It refers to the container, so each value the algorithm produces can be added to the end of that container.

python
Notes on the code
  • std::back_inserter(dest) names the container that should grow.
  • Each value written by std::copy is appended to dest.
  • dest starts empty and ends with three elements.

The back_inserter is needed here because an ordinary destination sequence cannot grow on its own. Without a reference to dest, the copying algorithm would have nowhere to place the new values beyond the positions that already exist.

Mistakes Beginners Make with Size and Values

  • Common mistake

    Expecting replace() or sort() to add or remove elements

    What it looks like

    Calling replace() on a container of three values and assuming it now holds four.

    Why it fails

    These algorithms change element values without changing the number of elements. The size stays the same.

    Do this instead

    If the count must change, call push_back() or erase() on the container, or use a back_inserter when an algorithm must write into a growing container.

  • Common mistake

    Treating a sequence as if it identifies the container

    What it looks like

    Passing only a begin and end position to an algorithm and expecting it to append values somewhere.

    Why it fails

    A sequence does not identify the container that holds its elements, so the algorithm cannot grow that container.

    Do this instead

    Give the algorithm a back_inserter that refers to the container, or perform the add operation on the container directly.

  • Common mistake

    Calling push_back() when the goal is to overwrite a value

    What it looks like

    Using push_back(9) to change the 2 in the list 1, 2, 3 to 9.

    Why it fails

    push_back() appends a new element. It does not replace the value already in a position, so the container grows instead.

    Do this instead

    Use an operation that changes values in existing positions, such as replace() for matching values.

Choosing Between an Algorithm, back_inserter, and Direct Operations

GoalSuitable approachEffect on the number of elements
Change matching values in placereplace()Unchanged
Rearrange existing values into ordersort()Unchanged
Add elements from an algorithm's outputAlgorithm connected through a back_inserterIncreases as values are written
Add one element at the endpush_back() on the containerIncreases by one
Remove one elementerase() on the containerDecreases by one

Matching the task to the operation that owns the change

A useful test is to ask whether the result needs a different number of elements. If the answer is no, an algorithm that changes values, such as replace() or sort(), may be suitable. If the answer is yes, the operation must reach the container itself, either by calling push_back() or erase() directly, or by connecting an algorithm to the container through a back_inserter.

Practice: Classifying Operations by Effect

EASY

A container holds the values 5, 7, 7, 2. For each task below, decide whether the operation changes only values, or whether it changes the number of elements, and name the operation you would use. (a) Change every 7 to 8. (b) Add the value 1 to the end. (c) Remove the element at index 0. (d) Sort the values into ascending order.

Hints
  • Ask first whether the number of elements must change.
  • Operations that overwrite or rearrange existing positions leave the size unchanged.
  • push_back() and erase() are called on the container and change its size.

Key Takeaways for Container Operations

  • Algorithms such as replace() and sort() can change element values without changing the number of elements.
  • A sequence does not identify the container that holds its elements, so an algorithm working only on a sequence cannot grow or shrink that container.
  • Use direct container operations such as push_back() or erase() when adding or removing elements directly.
  • Use a back_inserter to connect an algorithm to a container when the algorithm must add elements.

At a glance

  • Changing what is stored and changing how many elements are stored are different jobs.
  • replace() and sort() change values or order within existing positions, so the size stays the same.
  • push_back() and erase() are called on the container and change its number of elements.
  • A back_inserter connects an algorithm to the container that should grow when the algorithm adds elements.

Related concepts

More concepts starting with C