有关bind一些困惑解答

这篇具有很好参考价值的文章主要介绍了有关bind一些困惑解答。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

先看如下代码:

double my_divide (double x, double y) {return x/y;}

class A {
public:
    void fun_3(int k,int m) {
        std::cout << "print: k = "<< k << ", m = " << m << std::endl;
    }
};
int main()
{
    A a;
    //f5的类型为 function<void(int, int)>
    auto f5 = std::bind(&A::fun_3, &a, std::placeholders::_1, std::placeholders::_2); //使用auto关键字
    f5(10, 20);												//调用a.fun_3(10,20),print: k=10,m=20

    function<void(int, int)> fc = std::bind(&A::fun_3, a,std::placeholders::_1,std::placeholders::_2);
    fc(10, 20);  

    auto fn_half = std::bind (my_divide,std::placeholders::_1,2);      
    cout<<fn_half(4)<<endl;    
    auto fn_half1 = std::bind (&my_divide,std::placeholders::_1,2);    
    cout<<fn_half1(4)<<endl;  

    return 0;
}

对于&a和a都是可以正确编译执行,结果正确,往常我总是用&a的写法,传的是指针进去,所以见到绑定成员函数,第二个参数传的是a,本身对象而感到困惑

查阅资料得出:

这个是bind关于绑定成员函数的源码

template<typename _Result, typename _Func, typename... _BoundArgs>
struct _Bindres_helper
  : _Bind_check_arity<typename decay<_Func>::type, _BoundArgs...>
{
  typedef typename decay<_Func>::type __functor_type;
  typedef _Bind_result<_Result,
                       __functor_type(typename decay<_BoundArgs>::type...)>
    type;
};

template<typename _Result, typename _Func, typename... _BoundArgs>
inline
typename _Bindres_helper<_Result, _Func, _BoundArgs...>::type
bind(_Func&& __f, _BoundArgs&&... __args)
{
  typedef _Bindres_helper<_Result, _Func, _BoundArgs...> __helper_type;
  return typename __helper_type::type(std::forward<_Func>(__f),
                                      std::forward<_BoundArgs>(__args)...);
}

在这个模板函数中,_Bindres_helper 类模板用于根据 _Func_BoundArgs 推导绑定结果的类型。它还使用 typename decay<_Func>::type 去除 _Func 的引用和修饰符,以便获得准确的函数类型。然后它返回创建的绑定对象的实例。

综上所述,当调用 std::bind 绑定成员函数时,需要传入成员函数的指针(或可调用对象)、成员函数所属的对象(或指向该对象的指针)、以及任何要为成员函数提供的参数。通过源码中的模板函数重载选择正确的实现,并返回创建的绑定对象。

 bind(_Func&& __f, _BoundArgs&&... __args)

怎么做到绑定成员函数指针,和对象或对象指针的,,还有临时变量,右值等等

是因为用到了&&右值引用和引用折叠

  • 对于 _Func&& __f 这个参数,如果传递给 std::bind 的是一个右值,那么 _Func 将会被推导为该右值的类型,同时右值引用保持原样,因此可以接收对象的右值引用。
  • 如果传递给 std::bind 的是一个左值,根据引用折叠规则,_Func 将被推导为左值的引用类型,即 _Func&。这意味着它可以接收对象的左值引用。

同样地,在 _BoundArgs&&... __args 这个参数中,根据引用折叠规则,如果传递给 std::bind 的是右值,那么 _BoundArgs__args 将会被推导为右值引用类型,并保持原样。这意味着它们可以接收对象的右值引用列表。如果传递给 std::bind 的是左值,那么它们将被推导为左值引用类型,即 _BoundArgs&__args&。这意味着它们可以接收对象的左值引用列表。

综上所述,通过引用折叠规则和模板推导,std::bind 函数的参数可以接收对象和对象的指针(作为左值引用)

但是但是!虽然

auto boundFunc = std::bind(&MyClass::printMessage, obj, "Hello, world!");,虽然参数传递了一个对象 obj(而不是对象的指针或引用),但这个代码仍然能够编译和运行,并且没有出现错误。这是因为 std::bind 函数可以自动推断对象 obj 的正确类型。std::bind 函数使用了完美转发(perfect forwarding)来处理参数,因此它能够处理对象按值传递的情况。

std::bind 函数在内部会对对象 obj 进行一次拷贝,以便将其绑定到成员函数 MyClass::printMessage但是,请注意,如果对象很大或者具有复杂的拷贝语义,就需要谨慎使用这种方式。

为了确保代码的健壮性和可维护性,建议在使用 std::bind 时,仍然传递指向对象的指针或引用作为 std::bind 的参数。这样可以更清晰地表达意图,并避免潜在的拷贝开销或对象生命周期问题。所以,下面的代码更推荐:

传指针的方式:

MyClass obj;
auto boundFunc = std::bind(&MyClass::printMessage, &obj, "Hello, world!");

传引用的方式:

MyClass obj;
auto boundFunc = std::bind(&MyClass::printMessage, std::ref(obj), "Hello, world!");

建议阅读:

【C++】C++11的std::function和std::bind用法详解_Yngz_Miao的博客-CSDN博客

C++ STL初识:bind封装函数讲解 - hugeYlh - 博客园 (cnblogs.com)

 C++11新特性——std::bind参数绑定_山河君的博客-CSDN博客文章来源地址https://www.toymoban.com/news/detail-617788.html

到了这里,关于有关bind一些困惑解答的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 有关 Rust 交叉编译的一些思路 (仅供参考)

    近来, 使用 Rust 语言开发的应用程序, 渐渐融入了开发者以及普通用户的日常生活. 它们不仅出现在我们常用的工作平台上, 不少嵌入式设备或者云服务器上也多见它们的身影. Rust 是一种需要编译的语言, 且一些 crate 仍需要 C/C++ 的构建环境. 大多数时候, 在 Rust 工具链 (toolchai

    2024年02月09日
    浏览(32)
  • 有关MySQL onlinedb数据库的一些查询语句

    (1)查询users表,列出用户的所有信息。 SELECT * FROM users; (2)查询goods表,列出商品编号、名称和进货量(库存量+销售量,列名为purchases). SELECT gid, gname, (gquantity + gsale_qty) AS purchases FROM goods; (3)查询users表,找出2000年以后出生的用户,列出用户名、性别和所在城市。 SELECT uname,

    2024年02月07日
    浏览(35)
  • 对于xshell连接不上虚拟机的一些解答

    如果你发现你可以在虚拟机内ping通 之后,在你电脑dos下也可以ping通。 然而,还是发现你的xshell连接不上虚拟机。 这里使用ifconfig   我发现这个地址是在变化的,之前是129,现在是131,所以这样再到xshell,在连接属性那里,把地址改了就可以了,再重新连接,OK了。   本文

    2024年02月07日
    浏览(28)
  • 【C++】引用之带你“消除”C语言版数据结构教材的一些困惑(虽然是C++的内容,但是强烈建议正在学习数据结构的同学点进来看看)

    👀樊梓慕: 个人主页  🎥 个人专栏: 《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C++》 🌝 每一个不曾起舞的日子,都是对生命的辜负 目录 前言 引用的概念 引用的特性 引用的使用场景 引用和指针的区别 C语言版数据结构教材的解惑 不知道

    2024年02月08日
    浏览(36)
  • 【C++11】 包装器 | bind

    function包装器 也被叫做 适配器 C++11中function本质是 类模板, 也是一个包装器 意义在于 对可调用对象类型进行封装再适配 可调用对象:函数指针 / lambda / 仿函数 需要包含 头文件 functional 模板参数 Ret : 被调用函数的返回类型 …Args作为参数包,这个参数包中包含0到任意个模

    2024年02月12日
    浏览(27)
  • 有关TAA抗锯齿的简单介绍和在UE4中解决一些简单的抗锯齿问题

    在计算机图形学中,锯齿是由于图像中的几何形状或颜色值变化在像素层面上表现不充分,导致图像边缘或细节处出现明显的阶梯状或锯齿状现象。这是由于计算机图形学是基于离散化的表示方法,将连续的几何形状或颜色值转换为离散的像素值,导致图像的细节表现不充分

    2024年02月07日
    浏览(28)
  • C++ 11新特性之bind

    概述         std::bind是C++ 11中functional头文件提供的一个函数模板,它允许我们将函数或成员函数与其部分参数预先绑定在一起,形成一个新的可调用对象(英文为:Callable Object)。这个新的可调用对象可以在后续时机以剩余参数完成调用,这个机制对于事件处理、回调函

    2024年02月21日
    浏览(32)
  • C++11 包装器function和bind

    在C++11中,可以使用 std::function 来创建函数包装器。 std::function 是一个通用的函数对象,可以存储、复制和调用各种可调用对象,包括函数指针、函数对象、Lambda表达式等。 function 包装器也叫作适配器。 function 本质是一个类模板,也是一个包装器。 上面 func 可能是什么呢?

    2024年02月10日
    浏览(26)
  • C++11的std::function和bind绑定器

            在C++中,存在“可调用对象”这么一个概念。准确来说,可调用对象有如下几种定义:                 1、是一个函数指针                 2、是一个具有operator()成员函数的类对象(仿函数)                 3、是一个可转换为函数指针的类对象            

    2024年02月08日
    浏览(32)
  • C现代方法(第11章)笔记——指针

    —— 我记不清第十一条戒律是“你应该计算”还是“你不应该计算”了。 指针 是 C 语言最重要——也是最常被误解——的特性之一。由于指针的重要性,本书将用 3 章的篇幅对其进行讨论。本章侧重于基础知识,而第12章和第17章则介绍 指针的高级应用 。 本章将从 内存地

    2024年02月07日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包