...

/

Pass by Value When Applicable

Pass by Value When Applicable

Learn about the usage of pass-by value in different cases.

Passing by value: when and why to use it

Consider a function that converts a std::string to lowercase. In order to use the move-constructor where applicable, and the copy-constructor otherwise, it may seem like two functions are required:

Press + to interact
// Argument s is a const reference
auto str_to_lower(const std::string& s) -> std::string {
auto clone = s;
for (auto& c: clone) c = std::tolower(c);
return clone;
}
// Argument s is an rvalue reference
auto str_to_lower(std::string&& s) -> std::string {
for (auto& c: s) c = std::tolower(c);
return s;
}
TEST(MoveSemantics, StrToLower) {
std::cout << "tolower\n";
auto upper = std::string{"ABC"};
auto lower = str_to_lower(std::move(upper));
ASSERT_TRUE(upper.empty());
ASSERT_FALSE(lower.empty());
}

However, by taking the std::string by value instead, we can write one function that covers both cases:

Press + to interact
auto str_to_lower(std::string s) -> std::string {
for (auto& c: s) c = std::tolower(c);
return s;
}

Let's see why this implementation of str_to_lower() avoids unnecessary copying where possible. When passed a regular variable, shown as follows, the content of str is copy-constructed into ...