← SEARCHABLE ARCHIVE
C / C++ · 2026-07-30

C++ from Basics to Mastery — Part 14

What is the difference between copy and move?

INTERACTIVE READING MODE →

The articles written on this blog were created with the goal of teaching. Also, the information in the article may be incorrect, so please be careful.

It seems like a lot of copying will occur when inserting a large object into a vector or returning an object from a function. In C++, a distinction is made between copying, which duplicates the value as is, and movement, which takes over the resources of an object that is no longer needed.

copy

Copying creates a new object with the same values ​​as the original.

class Texture
{
public:
    explicit Texture(std::vector<unsigned char> pixels)
        : pixels(std::move(pixels))
    {
    }

private:
    std::vector<unsigned char> pixels;
};

Texture original(LoadPixels());
Texture copied = original;

copiedWhen a vector is created, the data inside the vector is also copied. Since the two objects are independent of each other, modifying the copied does not change the original.

Small values ​​have little copying cost, but objects with large buffers or many strings can be expensive.

movement

If the original is no longer used, the internal resources can be passed on to a new object.

Texture loaded(LoadPixels());
Texture equipped = std::move(loaded);

std::movedoes not directly transfer data. We change the object to treat it as a moveable value, and the actual work is done by the move constructor or move assignment operator.

movedloadedcan still be destroyed and new values ​​can be assigned. However, you should not expect the internal state to be the same as before.

loaded = Texture(LoadPixels()); //It is possible to substitute a new value.

Rule of Zero

If you manage memory directly with new and delete, you must consider copy constructor, copy assignment, move constructor, move assignment, and destructor together. If even one is implemented incorrectly, double free or memory leaks may occur.

class CharacterData
{
public:
    std::string name;
    std::vector<int> learnedSkills;
    std::unique_ptr<Weapon> weapon;
};

Using standard containers and smart pointers as members, each type manages its own resources. This method of not writing special member functions directly is called Rule of Zero.

unique_ptr cannot be copied; it can only be moved. This limitation prevents accidental duplication of sole ownership at the compile stage.

How to pass values

Large objects that only readconst T&When a function takes ownership, the method of receiving it as a value and then moving it is often used.

class Party
{
public:
    void Add(CharacterData character)
    {
        members.push_back(std::move(character));
    }

private:
    std::vector<CharacterData> members;
};

Party party;
CharacterData warrior;
party.Add(std::move(warrior));

CharacterData has unique_ptr as a member, so it cannot be copied but can only be moved. When adding an existing object, you must pass ownership using std::move or pass a temporary object.

Adding std::move everywhere is not optimal.

You must first decide whether it is a value that needs to be copied or if it is a value that you can pass ownership of. Moving is not a syntax for quick copying, but rather an expression of not relying on the original state after transferring resources.