我们可以使用右值引用作为参数 'passed through' 吗?

Can we use rvalue references for a parameter to be 'passed through'?

是否可以通过函数 'pass' 参数而不复制?

我们来打个比方:

std::string check(std::string in, int &maxLen)
{
    maxLen = std::max(maxLen, in.length());
    return in;
}

//main:
    int maxCnt = 0;
    std::cout
        << check("test, ", maxCnt)
        << check("two tests, ", maxCnt)
        << check("three tests, ", maxCnt)
        << maxCnt;
// would output: "test, two tests, three tests, 13"

我的 C++ 编译器 foo 还不够好,无法说明这是否已经被优化掉了。

check(...) 的签名必须是什么样子才能使临时参数永远不会 被复制?

我的第一个猜测是:

std::string && check(std::string &&in, int &maxLen)

如果这是正确的,实施会是什么样子?

备注:

如果您想避免输入字符串的任何副本,您应该将函数编写为:

std::string const& check(std::string const& input, int& maxLen) {
    maxLen = std::max(maxLen, input.size());
    return in;
}

const 引用传递的参数非常明显。为什么 return 呢?因为 RVO 不能省略这里的副本。当您在函数中构建一个对象(左值)并且 return 它(也包括左值参数)时,就会发生 RVO。编译器通过在它应该去的地方自动构建对象来省略副本。在这里,如果您 return 一个左值(std::string conststd::string),编译器将看到您想要将 return 值存储在某处,并且必须从您对该目的地的参考。通过使用 std::string const&,您将避免这种情况,因为来自 std::basic_ostreamoperator << 也处理 const 引用。

综上所述,根据上面的check()定义:

int max(0);
std::string toto("Toto");
std::string lvalue = check(toto, max); // copy
std::string const& const_ref = check(toto, max); // no-copy
std::cout << check(toto, max) << std::endl; // no-copy

最后一次调用中的重载决议将选择:

template <class CharT, class Traits, class Allocator>
std::basic_ostream<CharT, Traits>& 
     operator<<(std::basic_ostream<CharT, Traits>& os,
                const std::basic_string<CharT, Traits, Allocator>& str);
//              ^^^^^ const ref here for the string argument