std::copy_n
overlapping ranges
C++ programming
standard library
algorithms

Does stdcopy_n work with overlapping ranges?

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

std::copy_n is convenient when you know exactly how many elements to copy, but it is not the safe tool for every in-place move. When the source and destination overlap, the direction of copying matters, and using the wrong algorithm can produce undefined behavior.

What std::copy_n Is Designed For

std::copy_n(first, count, result) copies count elements starting at first into a destination beginning at result.

cpp
1#include <algorithm>
2#include <iostream>
3#include <vector>
4
5int main() {
6    std::vector<int> src{1, 2, 3};
7    std::vector<int> dst(3);
8
9    std::copy_n(src.begin(), 3, dst.begin());
10
11    for (int x : dst) {
12        std::cout << x << ' ';
13    }
14}

This is the ideal case: different ranges, no overlap, straightforward copy semantics.

Why Overlap Changes Everything

Suppose the destination begins inside the source range. If copying proceeds forward, an early write can overwrite values that later reads still need.

cpp
1#include <algorithm>
2#include <iostream>
3#include <vector>
4
5int main() {
6    std::vector<int> v{10, 20, 30, 40, 50};
7
8    // Do not rely on this with overlap.
9    std::copy_n(v.begin(), 3, v.begin() + 1);
10
11    for (int x : v) {
12        std::cout << x << ' ';
13    }
14}

Even if this seems to “work” on one compiler or one build, that does not make the behavior portable or defined.

Use the Direction-Aware Algorithm Instead

If you are shifting elements to the right and ranges overlap, std::copy_backward is usually the correct choice.

cpp
1#include <algorithm>
2#include <iostream>
3#include <vector>
4
5int main() {
6    std::vector<int> v{10, 20, 30, 40, 50};
7
8    std::copy_backward(v.begin(), v.begin() + 3, v.begin() + 4);
9
10    for (int x : v) {
11        std::cout << x << ' ';
12    }
13}

copy_backward walks from the end toward the beginning, so later source values are read before they are overwritten.

If the destination starts before the source, a normal forward std::copy is usually the right fit.

cpp
std::copy(v.begin() + 1, v.end(), v.begin());

That left-shift pattern is safe because earlier writes do not destroy future unread source elements.

What About Raw Memory?

For raw bytes or trivially copyable data, std::memmove is the overlap-safe primitive.

cpp
1#include <cstring>
2#include <iostream>
3
4int main() {
5    int data[] = {1, 2, 3, 4, 5};
6    std::memmove(data + 1, data, 3 * sizeof(int));
7
8    for (int x : data) {
9        std::cout << x << ' ';
10    }
11}

Do not generalize that to arbitrary object types with non-trivial invariants. memmove is a low-level byte operation, not an object-aware C++ algorithm.

A Simple Rule of Thumb

Use this decision guide:

  • no overlap and fixed count: std::copy_n
  • overlap while shifting right: std::copy_backward
  • overlap while shifting left: std::copy
  • overlapping raw bytes: std::memmove

That is easier to remember than trying to reason through every case from scratch.

Containers Do Not Change the Rule

Whether you are working with std::vector, std::string, or a raw array, overlap safety still depends on the algorithm you choose. The container may manage storage, but it does not make copy_n magically overlap-aware.

That is why it helps to think in terms of iterator ranges rather than container type. Once the ranges overlap, the same directional reasoning applies.

Common Pitfalls

The biggest mistake is assuming std::copy_n behaves like memmove when ranges overlap. It does not.

Another issue is testing on one platform, seeing acceptable output, and concluding the code is safe. Undefined behavior often looks harmless until it does not.

A third problem is reaching for memmove on non-trivial C++ objects when the standard algorithms are the correct tool.

Summary

  • 'std::copy_n is intended for normal copying, not as a general overlap-safe move.'
  • Overlap safety depends on copy direction.
  • Use copy_backward for right-shift overlap and copy for left-shift overlap.
  • Use memmove only for raw or trivially copyable memory scenarios.
  • If overlap is possible, choose the algorithm deliberately instead of hoping the copy order works out.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.