c++11随记:std::bind及 std::placeholders

一 使用场景

先将可调用的对象保存起来,在需要的时候再调用,是一种延迟计算的思想。不论是普通函数、函数对象、还是成员函数,成员变量都可以绑定,其中成员函数都可以绑定是相当灵活的。

二 头文件

定义于头文件

#include <functional>

三 bind原型

a.)

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

b.)

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

四 绑定普通函数

头文件

#include <functional>
#include <iostream>

定义函数

int TestFunc(int a, char c, float f)
{
    std::cout << a << std::endl;
    std::cout << c << std::endl;
    std::cout << f << std::endl;
    return a;
}

绑定函数:

    auto fun1 = std::bind(TestFunc, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
    auto fun2 = std::bind(TestFunc, std::placeholders::_2, std::placeholders::_3, std::placeholders::_1);
    auto fun3 = std::bind(TestFunc, std::placeholders::_1, std::placeholders::_2, 98.77);

使用:

  fun1(30, 'C',100.1);
  fun2(100.1, 30, 'C');
  fun3(30,'C');

说明:
fun1说明)
占位符->第一个参数和函数第一个参数匹配(int),第二个参数和第二个参数匹配(char),第三个参数和第三个参数匹配
fun2说明)
显然,可以通过占位符调整顺序,fun2绑定说明
占位符->第二个参数和函数第一个参数匹配(int),第三个参数和第二个参数匹配(char),第一个参数和第三个参数匹配
fun3说明:
占位符->第一个参数和函数第一个参数匹配(int),第二个参数和第二个参数匹配(char),第三个参数默认为98.77
如果第三个参数也要填的话,会被忽略掉

  fun3(30,'C',8.9);

上面的参数8.9将会忽略掉

五 绑定成员函数

定义一个测试类:

class TestClass
{
public:
    int ClassMember(int a) { return 55+a; }
    int ClassMember2(int a,char ch,float f)
    {
        std::cout <<ch <<" "<< f << " "<<a<<std::endl;
        return 55+a;
    }
    static int StaticMember(int a) { return 66+a; }
};

先看一个简单的绑定

    TestClass test;
    auto fun4 = std::bind(&TestClass::ClassMember,test,std::placeholders::_1);
    fun4(4);

通过对象test绑定,和绑定普通函数一样,用一个占位符占用绑定位置,当有多个参数时:

 auto fun5 = std::bind(&TestClass::ClassMember2,test,std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
 fun5(1,'A',3.1);

绑定静态成员函数就更简单了

    auto fun6 = &TestClass::StaticMember;
    fun6(3);

auto的类型

    std::function<int(int)> fun7 = &TestClass::StaticMember;

六 绑定成员变量

定义一个有public成员变量的测试类

class TestClass2
{
public:
    TestClass2()
        :m_a(100)
    {}
public:
    int m_a;
};

绑定成员变量

 TestClass2 test2;
 auto fun8 = std::bind(&TestClass2::m_a,std::placeholders::_1);

使用

  int var =fun8(test2);
  std::cout<<var<<std::endl;

七 绑定仿函数

定义测试类

class TestClass3
{
public:
    TestClass3()=default;
    TestClass3(const TestClass3& obj)
    {
        std::cout<<"TestClass3 copy construct."<<std::endl;
    }
    void operator()(int a)
    {
        std::cout<<a<<std::endl;
    }
};

绑定使用

 TestClass3 test3;
 auto fun9 = test3;
 fun9(2018);

这里多定义了一个拷贝构造函数,多验证了一个东西,即绑定时调用了拷贝构造
即用test3拷贝构造了一个新的对象,并绑定这个对象,所以fun9是新的对象,跟test3没关系了。
实际上其他的类成员函数也是一样的,拷贝构造完再绑定

八 绑定成员函数,是拷贝构造新对象再绑定

修改下TestClass

class TestClass
{
public:
    TestClass(int a):m_a(a){}
    TestClass(const TestClass& obj)
    {
        m_a = obj.m_a+100;
        std::cout<<"copy construct."<<std::endl;
    }
    int ClassMember(int a) { std::cout<<" this:"<<this<<" :"<<&m_a<<" "<<m_a<<std::endl;return 55+a; }
    int ClassMember2(int a,char ch,float f)
    {
        std::cout <<ch <<" "<< f << " "<<a<<std::endl;
        return 55+a;
    }
    static int StaticMember(int a) {return 66+a; }
public:
    int m_a;
};;

测试:

    std::cout<<"------"<<std::endl;
    TestClass test(67);
    std::cout<<"&test "<<&test<<" "<<test.m_a<<" &test.m_a "<<&test.m_a<<std::endl;
    auto fun4 = std::bind(&TestClass::ClassMember,test,std::placeholders::_1);
    fun4(4);
    fun4(4);
    std::cout<<"------"<<std::endl;

输出

------
&test 0x63fde4 67 &test.m_a 0x63fde4
copy construct.
 this:0x63fde0 :0x63fde0 167
 this:0x63fde0 :0x63fde0 167
------

显然调用了拷贝构造,指针地址也都不一样。
绑定静态成员函数就是直接绑定,没用拷贝构造

   std::cout<<"-----"<<std::endl;
   auto fun6 = &TestClass::StaticMember;
   fun6(3);
   std::cout<<"-----"<<std::endl;

输出

-----
-----

同样的,绑定成员对象也没有拷贝构造

   std::cout<<"------"<<std::endl;
   auto fun44 = std::bind(&TestClass::m_a,std::placeholders::_1);
   std::cout<<"TT:"<<fun44(test)<<" "<<test.m_a<<std::endl;
   std::cout<<"------"<<std::endl;

输出

------
TT:67 67
------

九 通过指针,取消拷贝构造

先定义一个对象,再利用std::function保存成员函数,在调用时候把test对象传进去即可,测试代码:

  TestClass test(67);
  std::cout<<"############"<<std::endl;
  std::function<int(TestClass*,int)> fg = &TestClass::ClassMember;
  fg(&test,5);
  std::cout<<"#################"<<std::endl;

十 通过引用保存,取消拷贝构造

  std::function<int(TestClass&,int)> hj = &TestClass::ClassMember;
  TestClass tt(8);
  std::cout<<&tt<<" "<<&tt.m_a<<std::endl;
  hj(tt,45);

输出:

0x62fde8 0x62fde8
 this:0x62fde8 :0x62fde8 8

看到this和m_a的地址是一样的,不写了

  • 22
    点赞
  • 111
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
当出现报错信息"Cannot find a valid baseurl for repo: base/7/x86_64"时,这通常是由于yum源配置有问题所致。解决这个问题的方法是修改yum源的配置。 首先,进入到/etc/yum.repos.d目录: ``` cd /etc/yum.repos.d ``` 然后,修改CentOS-Media.repo文件: ``` vi CentOS-Media.repo ``` 在CentOS-Media.repo文件中,将baseurl的值修改为以下内容: ``` baseurl=file:///mnt/cdrom/ file:///media/cdrecorder/ ``` 接下来,备份原来的yum源配置文件: ``` mv CentOS-Base.repo CentOS-Base.repo.bak ``` 创建一个挂载点: ``` mkdir /mnt/cdrom ``` 将文件挂载到创建的挂载点上: ``` mount /dev/cdrom /mnt/cdrom ``` 然后,更新yum源: ``` yum clean all yum makecache ``` 最后,再次修改CentOS-Media.repo文件,将gpgcheck的值修改为1,enabled的值修改为0,gpgkey的值修改为file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7。 通过以上步骤修改yum源的配置,可以解决报错信息"Cannot find a valid baseurl for repo: base/7/x86_64"。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [问题随记 —— Cannot find a valid baseurl for repo: base/7/x86_64](https://blog.csdn.net/qq_21484461/article/details/127148932)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [57 | Cannot find a valid baseurl for repo: base/7/x86_64](https://blog.csdn.net/u013916029/article/details/127736273)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值