Skip to content

Intermediate Gotchas

The Callback That Updated a Copy

two increments, and the counter never moves

void increment(int& value) { ++value; }

int main() {
    int count = 0;
    auto increment_count = std::bind(increment, count);

    increment_count();
    increment_count();

    std::cout << "count: " << count << '\n';
}

Run it. What does the counter print after two increments?

Answer
count: 0

The calls increment a counter, but not the one in main.

Why

std::bind does not preserve a reference merely because the target parameter is int&. It decay-copies each ordinary bound argument into the callable object, so count becomes a private stored int. Each call passes that stored value as an lvalue to increment, letting the private copy reach 2 while the original stays 0. This is valid code, so -Wall -Wextra emits no warning.

The fix

Wrap the argument in std::ref, or use a lambda that captures the original by reference:

auto increment_count = std::bind(increment, std::ref(count));
auto increment_count = [&count] { increment(count); };

Takeaway: std::bind copies bound arguments unless you wrap them in std::ref.

Try it: g++ -std=c++17 main.cpp -o demo && ./demo

Open in Compiler Explorer ↗ Quiz this entry