std::forward Visual Studio 13 的行为不像我预期的那样

std::forward Visual Studio 13 doesn't behave like I expect

本文关键字:Visual forward Studio std      更新时间:2023-10-16

我正在尝试学习一些基本的C++11,使用Scott Meyers在youtube上的讲座"一个有效的C++11/14采样器"

https://www.youtube.com/watch?v=BezbcQIuCsY

使用他的std::forward示例代码(讲座中的第19分钟),我编写了以下代码来理解std::forward 的效果

#include "stdafx.h"
#include <string>
#include <utility>
class A
{
public:
    void Foo(std::string&& s)
    {
        std::string s2 = std::forward<std::string>(s);
    }
};
int _tmain(int argc, _TCHAR* argv[])
{
    A a;
    std::string s3 = "Hello World";
    a.Foo(s3);
    a.Foo("Hello World");
    return 0;
}

令人惊讶的是,它没有编译,a.Foo(s3)不能隐式地从左值转换为右值。所以我把a.Foo(s3);改成了a.Foo(std::move(s3));,现在它可以编译了。然而,在对Foo的两次调用中,std::forward<std::string>(s);都被解析为右值,并发生了移动操作(由于其缓冲区被窃取,s被重置为"")。

所以我真的不明白std::forward有什么好处,什么时候适用。我在这里错过了什么?

在不涉及模板参数推导/引用折叠的情况下调用std::forward<>是没有意义的。

转发引用(Scott Meyers曾称之为"通用引用")的意义在于,根据您收到的内容的价值类别,您也可以转发该价值类别。

但在这里,你一点也不困惑什么是价值类别,它是静态的。

以下是一个具有模板参数推导的上下文:

template<typename T>
void f(T&& t) // T is to be deduced, && might be collapsed
{
  g(std::forward<T>(t)); // will keep the category value
}
f(std::string{"hey"}); // T inferred std::string&&, so the parameter type is `std::string&& &&`, which is collapsed to `std::string &&`.

您需要一个转发引用:

#include <string>
#include <utility>
class A
{
public:
    template <typename String>
    void Foo(String&& s)
    {
        std::string s2 = std::forward<String>(s);
    }
};

int main()
{
    A a;
    std::string s3 = "Hello World";
    a.Foo(s3);
    a.Foo("Hello World");
    return 0;
}

实例