Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Move semantics

Use case

Efficiently transfer ownership of large binary buffers when parsing Mach-O segments.

Explanation

When analyzing large binaries, we do not want to copy megabytes of data. Move semantics lets us transfer ownership of buffers efficiently. The new owner steals the pointer, leaving the old object empty.

Code

#include <cstdint>
#include <iostream>
#include <utility>
#include <vector>

struct Segment {
  std::string name;
  std::vector<uint8_t> data;

  Segment(const std::string &n, size_t size) : name(n), data(size, 0xFF) {
    std::cout << "Constructed segment: " << name << " (" << size
              << " bytes).\n";
  }

  // Move constructor.
  Segment(Segment &&other) noexcept
      : name(std::move(other.name)), data(std::move(other.data)) {
    std::cout << "Moved segment.\n";
  }

  // Copy constructor.
  Segment(const Segment &other) : name(other.name), data(other.data) {
    std::cout << "Copied segment.\n";
  }
};

Segment loadSegment() {
  Segment seg("__TEXT", 1024 * 1024);
  // Do not move here, as it might screw up RVO.
  return seg;
}

int main() {
  std::cout << "Loading segment.\n";
  Segment text = loadSegment();

  std::cout << "Transferring to analyzer.\n";
  Segment analyzer_seg = std::move(text);

  std::cout << "Original segment name: " << text.name << "\n";
  std::cout << "Analyzer segment name: " << analyzer_seg.name << "\n";

  return 0;
}

View on GitHub.

Output

$ ./src/c++11/build/move-semantics
Loading segment.
Constructed segment: __TEXT (1048576 bytes).
Transferring to analyzer.
Moved segment.
Original segment name: 
Analyzer segment name: __TEXT