0

Suppose I have a callback function taking a string parameter. This callback function is invoked with a string object that is no longer needed at call site, and most likely this function will need to do some string processing. What would you suggest to use for the parameter - lvalue reference, rvalue reference, or const lvalue reference, or something else?

a. If I am concerned about achieving maximum performance.

b. If I am concerned about code clarity.

CallbackType callback = processMessage; // declared elsewhere

std::string message;

// Way 1: accept by lvalue reference
using CallbackType = std::function<void(std::string&)>;
callback(message);

// Way 2: accept by rvalue reference
using CallbackType = std::function<void(std::string&&)>;
callback(std::move(message));

// Way 3: accept by const lvalue reference
using CallbackType = std::function<void(const std::string&)>;
callback(message);

// Way 4: accept by lvalue
using CallbackType = std::function<void(std::string)>;
callback(message); // copy
callback(std::move(message)); // move

Way 1 seems to be the fastest (function can do string processing with the original string, avoiding any copy or move) but looks a bit confusing (people may wonder if they need to change this parameter).

Way 3 seems to be the most widely used way but is the slowest as the function will have to make a copy of passed string before processing.

Way 2 is probably in the middle by performance.

UPDATE: Based on answers, added way 4 (caller can decide whether to copy or move).

1 Answer 1

3

You can accept it by value and have the caller invoke std::move() on the argument. This way the callee gets its own copy and the caller can decide whether to copy or move.

Accepting by r-value or non-const reference, though, saves from calling the move constructor. In other words, if you are minimizing the number of instructions executed then accept the string by a reference.

Sign up to request clarification or add additional context in comments.

4 Comments

I decided to accept by value, as you suggested (it turned out that I cannot use non-const ref because there can be several subscribers for whom I should call the callback function). But I'm confused by a part of your answer. It's clear that accepting by non-const ref saves from calling the move constructor, but why you say that accepting by r-value saves from calling the move constructor. Is it a typo or I miss something?
@4LegsDrivenCat I meant by r-value reference.
Yes, but by definition accepting by rvalue reference implies move constructor will be called.
@4LegsDrivenCat E.g. void foo(std::string&&) does not involve a move constructor.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.