C++11coreintermediate
Move Semantics (C++11 Addition)
C++11 · Modern Revolution · Compiler flag: -std=c++11
Explanation
Transfers resources from temporary objects, avoiding copies, using rvalue references.
Real-World Scenario
Move large data buffers in a network application to reduce overhead.
Quick Snippet
snippet.cpp
std::vector<int> vec; vec = std::move(otherVec);Full Example
move_semantics.cpp
// CodeNebula - C++11 Example: Move Semantics
// Compile: g++ -std=c++11 -Wall -Wextra -o example move_semantics.cpp
// Demonstrates move semantics with std::move and move-aware classes.
// Move semantics transfer ownership of resources instead of copying,
// dramatically improving performance for objects managing heap memory.
#include <iostream>
#include <string>
#include <vector>
#include <utility>
// Real-world scenario: a buffer class that manages dynamic memory
class Buffer {
int* data_;
std::size_t size_;
std::string name_;
public:
// Constructor
Buffer(const std::string& name, std::size_t size)
: data_(new int[size]()), size_(size), name_(name)
{
std::cout << " [Construct] " << name_ << " (size=" << size_ << ")" << std::endl;
for (std::size_t i = 0; i < size_; ++i) data_[i] = static_cast<int>(i);
}
// Copy constructor (expensive: allocates + copies)
Buffer(const Buffer& other)
: data_(new int[other.size_]), size_(other.size_), name_(other.name_ + "_copy")
{
std::cout << " [Copy] " << name_ << " from " << other.name_ << std::endl;
for (std::size_t i = 0; i < size_; ++i) data_[i] = other.data_[i];
}
// Move constructor (cheap: steals resources)
Buffer(Buffer&& other) noexcept
: data_(other.data_), size_(other.size_), name_(std::move(other.name_))
{
std::cout << " [Move] " << name_ << std::endl;
other.data_ = nullptr;
other.size_ = 0;
}
// Destructor
~Buffer()
{
std::cout << " [Destroy] " << (name_.empty() ? "(moved-from)" : name_)
<< std::endl;
delete[] data_;
}
void print() const
{
std::cout << " " << name_ << ": [";
for (std::size_t i = 0; i < size_; ++i) {
if (i > 0) std::cout << ", ";
std::cout << data_[i];
}
std::cout << "]" << std::endl;
}
std::size_t size() const { return size_; }
};
// Function that returns a Buffer (benefits from move on return)
Buffer createBuffer(const std::string& name, std::size_t size)
{
Buffer b(name, size);
return b; // move (or NRVO) applies here
}
int main()
{
// ------------------------------------------------------------------
// 1. Copy vs move
// ------------------------------------------------------------------
std::cout << "=== Copy vs Move ===" << std::endl;
Buffer original("Original", 5);
original.print();
Buffer copied(original); // copy constructor
copied.print();
Buffer moved(std::move(original)); // move constructor
moved.print();
std::cout << " Original size after move: " << original.size() << std::endl;
std::cout << std::endl;
// ------------------------------------------------------------------
// 2. std::move with standard library types
// ------------------------------------------------------------------
std::cout << "=== std::move with std::string ===" << std::endl;
std::string src = "Hello, World!";
std::string dst = std::move(src);
std::cout << " dst: \"" << dst << "\"" << std::endl;
std::cout << " src after move: \"" << src << "\"" << std::endl;
std::cout << std::endl;
// ------------------------------------------------------------------
// 3. std::move with vectors (moves entire internal buffer)
// ------------------------------------------------------------------
std::cout << "=== std::move with std::vector ===" << std::endl;
std::vector<int> v1 = {1, 2, 3, 4, 5};
std::vector<int> v2 = std::move(v1);
std::cout << " v2 size: " << v2.size() << std::endl;
std::cout << " v1 size after move: " << v1.size() << std::endl;
std::cout << std::endl;
// ------------------------------------------------------------------
// 4. Return value optimization with move
// ------------------------------------------------------------------
std::cout << "=== Factory function ===" << std::endl;
Buffer fromFactory = createBuffer("Factory", 3);
fromFactory.print();
std::cout << std::endl;
std::cout << "=== Cleanup ===" << std::endl;
return 0;
}
/*
Expected output (destructor order may vary, NRVO may elide some moves):
=== Copy vs Move ===
[Construct] Original (size=5)
Original: [0, 1, 2, 3, 4]
[Copy] Original_copy from Original
Original_copy: [0, 1, 2, 3, 4]
[Move] Original
Original: [0, 1, 2, 3, 4]
Original size after move: 0
=== std::move with std::string ===
dst: "Hello, World!"
src after move: ""
=== std::move with std::vector ===
v2 size: 5
v1 size after move: 0
=== Factory function ===
[Construct] Factory (size=3)
Factory: [0, 1, 2]
=== Cleanup ===
[Destroy] Factory
[Destroy] Original
[Destroy] Original_copy
[Destroy] (moved-from)
*/
Run command
g++ -std=c++11 -Wall -Wextra -o example move_semantics.cpp