# Using absl::Cord for Efficient String Manipulation in C++

> Learn how absl::Cord offers efficient C++ string manipulation with zero-copy slicing and O(1) concatenation. Optimize your code by avoiding expensive string copies.

- Repository: [Abseil/abseil-cpp](https://github.com/abseil/abseil-cpp)
- Tags: how-to-guide
- Published: 2026-07-16

---

**absl::Cord** is Abseil's rope-style string class that eliminates expensive copies by storing data in a tree of immutable fragments, enabling zero-copy slicing and O(1) concatenation.

For applications requiring efficient string manipulation on large or fragmented text, `std::string` often becomes a performance bottleneck due to repeated memory allocations and copies. The **absl::Cord** class in the `abseil/abseil-cpp` repository solves this by representing strings as a tree of reference-counted fragments rather than contiguous buffers. This design allows developers to perform complex string operations with minimal memory overhead even when processing payloads of hundreds of megabytes.

## Architectural Advantages of absl::Cord

Unlike standard strings that store data in a single contiguous block, `absl::Cord` manages a **tree of cord fragments** that can be flat buffers, external memory, or other cords. This structure, defined in [`absl/strings/cord.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/strings/cord.h), provides several performance benefits.

### Zero-Copy Slicing

The `Subcord` method creates a new `Cord` instance that points to the same underlying fragments while adjusting only the offset and length. No memory is duplicated during this operation, making it possible to extract substrings from gigabyte-scale data in constant time without triggering `memcpy` operations.

### O(1) Concatenation

When you use `Append` or `operator+=`, the library constructs a new **concat node** that links the two operand cords. The actual byte data is not copied until a later flattening step, allowing you to build complex string compositions without intermediate allocations or reallocations.

### Lazy Flattening

Read-only operations access the fragment tree directly. When a contiguous view is finally required, the `Flatten()` method traverses the tree and copies the data once into a single buffer. This lazy approach ensures that you pay the copy cost only when absolutely necessary, such as when interfacing with legacy APIs requiring `char*` or `std::string`.

### Thread-Safe Read Access

All read-only operations on `absl::Cord` are lock-free because fragments are immutable after insertion. Multiple threads can safely iterate over or slice the same cord without synchronization overhead, as implemented in the thread-safe reference counting found in [`absl/strings/internal/cord_internal.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/strings/internal/cord_internal.h).

## Internal Data Structures

The power of `absl::Cord` comes from its sophisticated internal representation defined in the `absl/strings/internal/` directory.

The **CordRep** base class in [`absl/strings/internal/cord_internal.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/strings/internal/cord_internal.h) abstracts the different node types and handles reference counting. For small to medium data, **CordRepFlat** (defined in [`absl/strings/internal/cord_rep_flat.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/strings/internal/cord_rep_flat.h)) stores a simple contiguous block. For very large cords, **CordRepBtree** (from [`absl/strings/internal/cord_rep_btree.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/strings/internal/cord_rep_btree.h)) implements a balanced binary tree that maintains efficient access patterns even with extreme fragmentation.

## Practical Usage Examples

The following example demonstrates building cords from fragments, zero-copy slicing, external buffer wrapping, and flattening:

```cpp
#include "absl/strings/cord.h"
#include <iostream>

int main() {
  // 1️⃣ Build a cord from several fragments without copying.
  absl::Cord c1 = "Hello, ";
  absl::Cord c2 = "world!";
  absl::Cord c = c1;          // copy is cheap – just a reference
  c.Append(c2);               // O(1) concatenation, creates a concat node

  // 2️⃣ Zero-copy slicing.
  absl::Cord sub = c.Subcord(7, 5);   // "world"
  std::cout << sub << "\n";           // prints without extra allocations

  // 3️⃣ External buffer – no ownership transfer.
  const char* raw = "external data";
  absl::Cord ext = absl::Cord::External(
      raw, strlen(raw),
      [](const void*, size_t, const absl::Cord::ExternalRep*) {}); // no-op deleter
  std::cout << ext << "\n";

  // 4️⃣ When a flat string is finally needed.
  std::string flat = c.Flatten();     // copies once
  std::cout << "Flat size: " << flat.size() << "\n";

  // 5️⃣ Iterate over fragments (useful for zero-copy processing).
  for (absl::Cord::CharIterator it = c.char_begin(); it != c.char_end(); ++it) {
    // process each character; underlying data is accessed lazily.
    putchar(*it);
  }
  putchar('\n');
}

```

This program concatenates two strings, slices a view, wraps an external buffer, and finally flattens the whole composition with minimal copying.

## External Buffer Integration

For I/O pipelines where data arrives from external sources, `absl::Cord::External` (defined in [`absl/strings/cord.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/strings/cord.h)) allows wrapping existing buffers without taking ownership. You provide a custom deleter function, enabling zero-copy integration with memory-mapped files or network buffers owned by other subsystems.

## Performance Guidelines

**Use absl::Cord when:**

- Handling very large payloads (hundreds of MB) where concatenation or slicing would otherwise trigger excessive `memcpy` operations.
- Building streaming parsers that accumulate chunks from sockets or files before processing.
- Exposing read-only views of external data without copying into `std::string`.

**Prefer std::string when:**

- Working with small strings (less than 1KB) where the overhead of the tree structure outweighs copy costs.
- Performing frequent mutable in-place edits such as `replace` or `insert`, since `absl::Cord` is immutable after insertion.

## Debugging and Diagnostics

The `cordz` subsystem provides allocation statistics and fragmentation tracing for debugging. These features are controlled through the interfaces in [`absl/strings/internal/cordz_functions.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/strings/internal/cordz_functions.h). Enable cordz instrumentation to analyze memory usage patterns and optimize node allocation strategies in production applications.

## Summary

- **absl::Cord** stores strings as a tree of immutable fragments in [`absl/strings/cord.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/strings/cord.h), eliminating unnecessary copies during manipulation.
- **Zero-copy slicing** via `Subcord` and **O(1) concatenation** via `Append` make it ideal for large-scale text processing.
- **Lazy flattening** ensures contiguous data is materialized only when explicitly requested via `Flatten()`.
- The internal **CordRep** hierarchy ([`cord_internal.h`](https://github.com/abseil/abseil-cpp/blob/main/cord_internal.h), [`cord_rep_flat.h`](https://github.com/abseil/abseil-cpp/blob/main/cord_rep_flat.h), [`cord_rep_btree.h`](https://github.com/abseil/abseil-cpp/blob/main/cord_rep_btree.h)) provides memory-efficient storage for diverse data sizes.
- **External buffers** integrate without ownership transfer, and the **cordz** subsystem offers diagnostic capabilities for memory analysis.

## Frequently Asked Questions

### What is the difference between absl::Cord and std::string?

`std::string` stores characters in a single contiguous buffer, requiring reallocations and copies when concatenating or slicing. `absl::Cord` stores data in a **tree of fragments** (CordRep nodes), enabling reference counting and zero-copy operations. According to the `abseil/abseil-cpp` source code, this makes `Cord` significantly more efficient for large or frequently concatenated strings.

### How does absl::Cord achieve zero-copy concatenation?

When you call `Append` or use `operator+=` in [`absl/strings/cord.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/strings/cord.h), the library creates a new **concat node** (a CordRep subtype) that references both source cords. The actual byte data is not copied until you call `Flatten()` or access the data in a way that requires a contiguous view. This O(1) operation contrasts with `std::string`, which requires allocating a new buffer and copying all bytes.

### When should I flatten an absl::Cord?

Flatten when you need to pass the string contents to an API requiring a contiguous memory block (such as a C-style `char*` or `std::string`). The `Flatten()` method walks the fragment tree and copies data once into a single buffer. Avoid flattening if you only need to read or slice the data, as fragment-level iteration via `char_begin()` and `char_end()` provides zero-copy access.

### How can I monitor absl::Cord memory usage?

Enable the **cordz** instrumentation system by using the utilities in [`absl/strings/internal/cordz_functions.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/strings/internal/cordz_functions.h). This subsystem records allocation statistics, node counts, and fragmentation patterns. While it adds minimal overhead, cordz provides visibility into how the CordRep tree (including CordRepFlat and CordRepBtree nodes) consumes memory, helping you optimize for reduced allocations.