Sequences and Containers
Calling push_back() or erase() works on the container, which is why it can change the number of elements. An algorithm such as replace() or sort() works on the sequence of positions, which is why it changes values but leaves the count alone.
A Task That Seems to Need a Bigger Container
Suppose you have a container full of values and a task to perform on them. Sometimes the task looks as if it should change how many values the container holds. You might want to add a new value at the end, or drop a value you no longer need. It is natural to wonder whether the algorithm doing the work can simply grow or shrink the container as part of the job. This article explains why that is not automatic, and how the two kinds of work differ.
The source for this topic makes one central point: changing what is stored and changing how many elements are stored are different jobs. Algorithms such as replace() and sort() can change element values without changing the number of elements. Keep that idea in mind as you read, because the rest of the article follows from it.
What an Algorithm Actually Sees
An algorithm works on a sequence of elements. The sequence is the run of positions it reads and, when the operation requires it, writes. The algorithm is handed a range of positions, usually described by a beginning and an end, and it moves through that range doing its work. This is the whole of what it knows about the data.
Here is the key consequence. A sequence does not identify the container that holds its elements. The algorithm gets a view of the positions, not a handle to the container object itself. So when an algorithm finishes, it has no built-in way to say that the container should now have more positions or fewer. Changing a value at a position is possible because the position is right there in the range. Changing how many positions exist is a different action on a different object, and the sequence alone does not provide it.
Read the diagram from the bottom up. The algorithm reaches the elements through the sequence. The container holds the elements, and nothing in the sequence points back to the container. Because of that missing link, the algorithm can rewrite the values it reaches, but it has no route to alter the container's count.
Changing Values Versus Changing the Element Count
Changing values means overwriting what is stored at existing positions. The number of elements stays the same. Changing the element count means adding elements to the container or removing elements from it. The number of elements goes up or down, and the container itself must be acted on.
The source gives a practical test for telling these apart. The distinction is useful 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.
| Question | Changing values | Changing the element count |
|---|---|---|
| What is the goal? | Make existing positions hold different values | Add new elements or remove existing ones |
| Example operations named in the source | replace() and sort() | push_back() and erase(), or an algorithm connected to the container through back_inserter |
| Does the element count change? | No | Yes |
| What must the operation be able to reach? | The sequence of positions | The container itself |
Two kinds of work on a container, drawn from the distinction in the source
What do you think happens?
You call replace() on a container of five values, changing every occurrence of one value to another. After the call, how many elements does the container hold?
Reveal answer
Five, because replace() changes values without changing the number of elements.
The source states that algorithms such as replace() can change element values without changing the number of elements. Replacement overwrites existing positions, so the count stays the same.
Connecting an Algorithm to a Container
Sometimes an algorithm does need to add elements, and the task is best done with an algorithm rather than a loop you write by hand. The source handles this with the back_inserter. Its role is to act as the missing 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.
Think of the back_inserter as an adapter placed where the algorithm writes its output. Each time the algorithm produces a value, that value is handed to the back_inserter, which adds it to the end of the container. The algorithm itself still works on a sequence, but the back_inserter gives it a way to reach the container when new elements need a home.
Read the flow from left to right. The copy-style algorithm takes each value from the source and writes it through the back_inserter. Each write is routed to a push_back() on the destination, which appends the value. Because every write appends one element, the destination grows as the copy proceeds. The growth comes from the connection, not from the algorithm knowing anything about containers.
Direct Container Operations: push_back and erase
When you are adding or removing elements directly, you do not need an algorithm in the middle. The source names two direct container operations: push_back(), which adds an element to the end of the container, and erase(), which removes elements. You call these on the container itself, so they can change the element count as part of their own action.
Calling push_back() or erase() works on the container, which is why it can change the number of elements. An algorithm such as replace() or sort() works on the sequence of positions, which is why it changes values but leaves the count alone.
Tracing replace() on a Small Container
The following example is an original illustration built to follow the rule from the source. It uses a container of three values and a replace() call that changes every 3 to a 9. Trace what happens to the values and to the size.
Replacing Values Without Changing Size
A container holds the values 3, 7, and 3. A replace() call changes every 3 to 9. What does the container hold afterward, and how many elements does it have?
- 1Identify the range
replace()receives the positions of the container. It walks through all three positions. - 2Check position 1
The value is 3, which matches. The algorithm overwrites that position with 9.
- 3Check position 2
The value is 7, which does not match. The position is left as it is.
- 4Check position 3
The value is 3, which matches. The algorithm overwrites that position with 9.
- 5Check the count
No position was added or removed. The container still has three positions, so the size is unchanged.
The container now holds 9, 7, and 9. It still has three elements.
Compare the two states in the diagram. Positions 1 and 3 changed, and position 2 did not. The number of positions stayed at three in both states. That is the behavior the source describes: replace() changes element values without changing the number of elements.
Choosing Between an Algorithm Connection and a Direct Call
Once you know the distinction, the choice of tool follows from the task. Start by asking whether the operation must change the number of elements. If it only needs to change values, an algorithm such as replace() or sort() is a suitable choice, and it does not need a container operation at all. If the task must add or remove elements, the operation needs a way to act on the container itself.
- Changing values only: use an algorithm such as
replace()orsort(), which works on the sequence. - Adding elements while using an algorithm: connect the algorithm to the container with a
back_inserter, so each output is added to the end. - Adding or removing elements directly: call
push_back()to add at the end, orerase()to remove elements, on the container itself.
Mistakes Beginners Make With Sequences
Common mistake Expecting an algorithm to grow or shrink the container just because the task seems to need a different count
What it looks likeAssuming that replace() will add a new element when a replacement seems to call for more values
Why it failsThe source states that changing what is stored and changing how many elements are stored are different jobs. An algorithm working on a sequence does not have a route to the container's size.
Do this insteadDecide first whether the task changes values or changes the element count, then choose the tool that matches.
Common mistake Using replace() or sort() when the task is to add or remove elements
What it looks likeTrying to make a container longer by calling sort() on it
Why it failssort()changes the order of values in the positions it reads. It does not add or remove elements, so the count stays the same.Do this insteadUse push_back() to add or erase() to remove when the element count itself must change.
Common mistake Writing an algorithm's output to a container without a connection to it
Why it failsThe sequence alone does not tell the algorithm where added elements belong. Without a way to refer to the container, there is no defined place for the new elements.
Do this insteadConnect the algorithm to the container with a back_inserter when the algorithm must add elements.
Applying the Rule to New Tasks
For each task, decide whether it changes values only, or changes the number of elements. Then name the tool you would reach for: an algorithm such as replace() or sort(), a back_inserter connection, or a direct push_back() or erase() call. Task A: change every 0 in a container to 1. Task B: add a new reading to the end of a container. Task C: arrange the values in order. Task D: remove the last element from a container.
Hints
- Ask first whether the element count must change. Tasks A and C only change values or order.
- Task B adds an element. Consider whether an algorithm writing its output needs a connection, or whether a direct call is simpler.
- Task D removes an element from the container itself, which points to a direct container operation.
Key Takeaways
- An algorithm working on a sequence can change element values, as
replace()andsort()do, but it cannot by itself change the size of the container, because a sequence does not identify the container that holds its elements. - Changing values and changing the number of elements are different jobs. Decide which one a task requires before choosing a tool.
- A
back_inserterconnects an algorithm to a container when the algorithm must add elements, so each output is added to the end of the container. - When adding or removing elements directly, use the container operations
push_back()orerase(), which act on the container itself.