我们可以使用右值引用作为参数 '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
是一个占位符,它应该适用于任何复杂类型
- 请提示我任何重复的问题
如果您想避免输入字符串的任何副本,您应该将函数编写为:
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 const
或 std::string
),编译器将看到您想要将 return 值存储在某处,并且必须从您对该目的地的参考。通过使用 std::string const&
,您将避免这种情况,因为来自 std::basic_ostream
的 operator <<
也处理 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
是否可以通过函数 '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
是一个占位符,它应该适用于任何复杂类型- 请提示我任何重复的问题
如果您想避免输入字符串的任何副本,您应该将函数编写为:
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 const
或 std::string
),编译器将看到您想要将 return 值存储在某处,并且必须从您对该目的地的参考。通过使用 std::string const&
,您将避免这种情况,因为来自 std::basic_ostream
的 operator <<
也处理 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