here are
与代码的结果略有不同。如评论中所述,编译器及其设置非常重要。特别是,您可能会注意到,所有情况下都有类似的运行时,但第一种情况除外,它的速度大约是第二种情况的两倍。
Passing rvalue!
const l value: 1357465
rvalue forwarding: 669589
Passing lvalue!
const l value: 744105
rvalue forwarding: 713189
1) 呼叫时
wrap1("test")
,因为该函数的签名需要
const std::string &
std::string
每次通话(即。
n
次),其中包含值的副本*。然后将该临时文件的常量引用传递到
func1
是从它构造的,它再次涉及一个副本(因为它是常量引用,所以不能从中移动,尽管它实际上是临时的)。即使函数按值返回,但由于RVO,如果使用返回值,该副本将保证被忽略。在这种情况下,不使用返回值,我不完全确定该标准是否允许编译器优化
temp
标准::字符串
在这种情况下执行两次。
wrap2("test")
,参数类型为
const char[5]
,并将其作为右值引用转发到
func2
标准::字符串
来自a的构造函数
const char[]
被称为复制值。导出的模板参数类型
T
是
const char[5] &&
const
不
成为一名
标准::字符串
常量字符[5]
wrap1(arg)
const string &
通过链,在中调用一个副本构造函数
功能1
.
4) 呼叫时
wrap2(arg)
T
是
5) 我假设您的测试旨在证明当需要在调用链的底部制作参数副本时,完美转发的优势(因此创建
临时雇员
). 在这种情况下,您需要替换
"test"
前两种情况下的论点
std::string("test")
为了真正拥有
std::string &&
并将你的完美转发改为
std::forward<T>(arg)
,如评论中所述。那样的话
the results
Passing rvalue!
const l value: 1314630
rvalue forwarding: 595084
Passing lvalue!
const l value: 712461
rvalue forwarding: 720338
这与我们之前的类似,但现在实际上调用了移动构造函数。
我希望这有助于解释结果。可能还有一些其他问题与函数调用的内联和其他编译器优化有关,这将有助于解释案例2-4之间较小的差异。
*由于短字符串优化,复制构造函数可能涉及也可能不涉及动态内存分配;感谢ytoledano在评论中提出这一点。此外,我在整个回答中都隐含着这样的假设,即拷贝比移动要昂贵得多,但情况并非总是如此。