性能比较:f(std :: string &&)vs f(T &&)

ban*_*ace 1 c++ rvalue-reference c++11

我试图理解使用WidgetURef::setName(URef作为一个通用参考,由Scott Meyers创造的术语)与WidgedRRef::setName(RRef作为R值参考)的性能影响:

#include <string>

class WidgetURef {
    public:
    template<typename T>
    void setName(T&& newName)
    {
        name = std::move(newName);
    }
    private:
        std::string name;
};

class WidgetRRef {
    public:
    void setName(std::string&& newName)
    {
        name = std::move(newName);
    }
    private:
        std::string name;
};

int main() {
    WidgetURef w_uref;
    w_uref.setName("Adela Novak");

    WidgetRRef w_rref;
    w_rref.setName("Adela Novak");
}
Run Code Online (Sandbox Code Playgroud)

我很欣赏通用引用应该使用std::forward,但这只是一个(不完美的)示例,以突出有趣的位.

问题 在这个特定的例子中,使用一个实现与另一个实现的性能影响是什么?虽然WidgetURef需要类型扣除,但它在其他方面是相同的WidgetRRef,不是吗?至少在这种特殊情况下,在两种情况下,参数都是r-value引用,因此不会创建临时值.这个推理是否正确?

背景 这个例子来自Scott Meyers的"Effective Modern C++"(p.170)的第25项.根据这本书(假设我的理解是正确的!),采用通用引用的版本T&&不需要临时对象而另一个需要临时对象std::string&&.我真的不明白为什么.

Max*_*kin 5

setName(T&& newName)with参数"Adela Novak"得到Tduduced const char (&)[12],然后分配给std::string.

setName(std::string&& newName)with参数"Adela Novak"创建一个临时std::string对象,然后移动分配给std::string.

第一个在这里效率更高,因为没有涉及的移动.