std::bind 如何按值获取可变参数参数,即使使用其通用引用? [英] How does std::bind take variadic arguments by value, even with its universal reference?

查看:33
本文介绍了std::bind 如何按值获取可变参数参数,即使使用其通用引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

std::bind() 的函数签名 如下:

template< class F, class... Args >
/*unspecified*/ bind( F&& f, Args&&... args );

所以 args 是一个可变参数模板通用参考,如果我理解正确的话.通用引用的传统模板类型推导规则如下:

So args is a variadic template universal reference, if I understand correctly. The traditional template type deduction rules for universal references are as follows:

  1. 如果传递给 T 的参数是左值,则将 T 推导为左值引用
  2. 如果传递给 T 的参数是右值,则将 T 推导为左值

... 我认为这些规则将分别应用于 args 中的每个 arg,这意味着所有左值都作为参数传入 std::bind()函子将通过引用传递.然而,这与下面的程序相矛盾:

... and I think these rules would apply to each arg in args individually, meaning that all lvalues passed into std::bind() as an argument to the functor would be passed by reference. However this contradicts the program below:

#include <iostream>
#include <functional>

void function(int& n) {
  n++;
}

int main() {
    int n = 0;
    auto functor = std::bind(function, n);
    functor();
    std::cout << n << std::endl; // 0, not 1.
    return 0;
}

为了让 n 通过引用传递,你必须通过 std::ref(n) 明确地这样做,这真的让我感到困惑(小) 我知道通用引用和完美转发.std::bind() 在使用通用引用时如何按值取值,否则会使用左值作为引用?

In order to get n to be passed by reference, you must do so explicitly via std::ref(n), which really confuses me given what (little) I know about universal references and perfect forwarding. How does std::bind() take anything by value when it uses universal references, which would otherwise consume lvalues as references?

推荐答案

它几乎与签名无关,它是一种设计选择.std::bind 当然必须以某种方式存储其所有绑定参数并将它们存储为值.普遍性"仅用于正确构建它们 - 通过移动或复制.

It has almost nothing to do with the signature, it is a design choice. std::bind must of course store all its bound arguments somehow and it stores them as values. The "universality" is only used to properly construct them - by move or copy.

std::ref 也按值存储,但由于其性质,包装的对象是存储"的.供参考.

std::ref is also stored by value but due to its nature, the wrapped object is "stored" by reference.

std::thread 具有完全相同的行为.有人可能会争辩说,默认情况下(移动)构建副本更安全,因为返回的两个对象往往比最有可能被捕获的本地对象存活时间更长.

std::thread has exactly the same behaviour. One can argue that (move) constructing a copy by default is safer because both returned objects tend to outlive locals which are the likeliest to be captured.

这篇关于std::bind 如何按值获取可变参数参数,即使使用其通用引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆