34

c++奇淫技巧之完美转发 - 简书

 3 years ago
source link: https://www.jianshu.com/p/eb699b92474c?
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
0.4572020.07.17 20:36:10字数 415阅读 390

解决什么问题

在介绍完美转发之前,我们先来看下面的一段代码。


void foo(const shape&)
{
  puts("foo(const shape&)");
}

void foo(shape&&)
{
  puts("foo(shape&&)");
}

void bar(const shape& s)
{
  puts("bar(const shape&)");
  foo(s);
}

void bar(shape&& s)
{
  puts("bar(shape&&)");
  foo(s);
}

int main()
{
  bar(circle());
}

我们猜下,上面会输出什么。
===============================留你思考=================================

circle()会生成一个右值,所以会调用bar(shape&&),这个时候参数s变为了左值,所以会调用foo(const shape&),所以以上的输出是:

bar(shape&&)
foo(const shape&)

如果我们希望保持bar函数收到的右值引用,我们就要变为下面的调用方式:

void bar(shape&& s)
{
  puts("bar(shape&&)");
  foo(std::move(s));
}

可以看到了,bar函数为了保证在转发参数的过程中,保持参数的值类别:左值的仍然是左值,右值的仍然是右值,不得不重载两个bar函数,那有什么简单的方法能够实现呢?

这就有了c++标准库中的std::forward,即转发引用(forwarding reference),也叫做万能引用(universal reference),具体到实现上来说就是:

template<typename T>
void bar(T &&s) {
    foo(std::forward<T>(s));
}

此时再看下面的输出:

circle temp;
bar(temp);
bar(circle());

大家应该能够很容易回答上来了。

本文介绍了c++中转发引用的使用场景:保证在转发参数的过程中,保持参数的值类别:左值的仍然是左值,右值的仍然是右值。

最后一段代码的输出,欢迎留言的。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK