Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7077407
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 28, 20262026-05-28T06:25:11+00:00 2026-05-28T06:25:11+00:00

This is basically a question about the readability, style, performance of 2 different approaches

  • 0

This is basically a question about the readability, style, performance of 2 different approaches to creating/passing a functor that points to a member method from within a class constructor/method.

Approach 1:

using namespace std::placeholders;
std::bind( &MyClass::some_method, this, _1, _2, _3 )

Approach 2:

[ this ](const arg1& a, arg2 b, arg3& c) -> blah { some_method( a, b, c ); }

I was wondering if using the lambda is just gratuitous in this situation, in some respects it is easier to see what is going on, but then you have to explicitly provide the arg types. Also i prefer not to have “using namespace whatever;” but then it makes the bind expression needlessly verbose (eg. _1 becomes std::placeholders::_1), and lambda avoids this issue.

Finally i should note that for the purposes of this question, some_method is a big function that does lots of things, and would be a pain to directly copy into a lambda body.

If this question seems too vague, then we can focus on answers to the performance differences, if any.

EDIT: A non-trivial use case.

MyClass::MyClass()
:    some_member_( CALLBACK_FUNCTOR )
{}

As you can see, the CALLBACK_FUNCTOR used in an initializer list (defined with approach 1 or 2) makes it difficult to scope a using declaration (afaik), and obviously we wouldnt bother wrapping a member method that we intended to call straight away.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-28T06:25:11+00:00Added an answer on May 28, 2026 at 6:25 am

    As far as readability and style are concerned, I think std::bind looks cleaner for this purpose, actually. std::placeholders does not have anything other than _[1-29] for use with std::bind as far as I know, so I think it is fine to just use “using namespace std::placeholders;”

    As for performance, I tried disassembling some test functions:

    #include <functional>
    
    void foo (int, int, int);
    
    template <typename T>
    void test_functor (const T &functor)
    {
        functor (1, 2, 3);
    }
    
    template <typename T>
    void test_functor_2 (const T &functor)
    {
        functor (2, 3);
    }
    
    void test_lambda ()
    {
        test_functor ([] (int a, int b, int c) {foo (a, b, c);});
    }
    
    void test_bind ()
    {
        using namespace std::placeholders;
        test_functor (std::bind (&foo, _1, _2, _3));
    }
    
    void test_lambda (int a)
    {
        test_functor_2 ([=] (int b, int c) {foo (a, b, c);});
    }
    
    void test_bind (int a)
    {
        using namespace std::placeholders;
        test_functor_2 (std::bind (&foo, a, _1, _2));
    }
    

    When foo() was not defined in the same translation unit, the assembly outputs were more or less the same for both test_lambda and test_bind:

    00000000004004d0 <test_lambda()>:
      4004d0:   ba 03 00 00 00          mov    $0x3,%edx
      4004d5:   be 02 00 00 00          mov    $0x2,%esi
      4004da:   bf 01 00 00 00          mov    $0x1,%edi
      4004df:   e9 dc ff ff ff          jmpq   4004c0 <foo(int, int, int)>
      4004e4:   66 66 66 2e 0f 1f 84    data32 data32 nopw %cs:0x0(%rax,%rax,1)
      4004eb:   00 00 00 00 00 
    
    00000000004004f0 <test_bind()>:
      4004f0:   ba 03 00 00 00          mov    $0x3,%edx
      4004f5:   be 02 00 00 00          mov    $0x2,%esi
      4004fa:   bf 01 00 00 00          mov    $0x1,%edi
      4004ff:   e9 bc ff ff ff          jmpq   4004c0 <foo(int, int, int)>
      400504:   66 66 66 2e 0f 1f 84    data32 data32 nopw %cs:0x0(%rax,%rax,1)
      40050b:   00 00 00 00 00 
    
    0000000000400510 <test_lambda(int)>:
      400510:   ba 03 00 00 00          mov    $0x3,%edx
      400515:   be 02 00 00 00          mov    $0x2,%esi
      40051a:   e9 a1 ff ff ff          jmpq   4004c0 <foo(int, int, int)>
      40051f:   90                      nop
    
    0000000000400520 <test_bind(int)>:
      400520:   ba 03 00 00 00          mov    $0x3,%edx
      400525:   be 02 00 00 00          mov    $0x2,%esi
      40052a:   e9 91 ff ff ff          jmpq   4004c0 <foo(int, int, int)>
      40052f:   90                      nop
    

    However, when the body of foo was included into the same translation unit, only the lambda had its contents inlined (by GCC 4.6):

    00000000004008c0 <foo(int, int, int)>:
      4008c0:   53                      push   %rbx
      4008c1:   ba 04 00 00 00          mov    $0x4,%edx
      4008c6:   be 2c 0b 40 00          mov    $0x400b2c,%esi
      4008cb:   bf 60 10 60 00          mov    $0x601060,%edi
      4008d0:   e8 9b fe ff ff          callq  400770 <std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)@plt>
      4008d5:   48 8b 05 84 07 20 00    mov    0x200784(%rip),%rax        # 601060 <std::cout@@GLIBCXX_3.4>
      4008dc:   48 8b 40 e8             mov    -0x18(%rax),%rax
      4008e0:   48 8b 98 50 11 60 00    mov    0x601150(%rax),%rbx
      4008e7:   48 85 db                test   %rbx,%rbx
      4008ea:   74 3c                   je     400928 <foo(int, int, int)+0x68>
      4008ec:   80 7b 38 00             cmpb   $0x0,0x38(%rbx)
      4008f0:   74 1e                   je     400910 <foo(int, int, int)+0x50>
      4008f2:   0f b6 43 43             movzbl 0x43(%rbx),%eax
      4008f6:   bf 60 10 60 00          mov    $0x601060,%edi
      4008fb:   0f be f0                movsbl %al,%esi
      4008fe:   e8 8d fe ff ff          callq  400790 <std::basic_ostream<char, std::char_traits<char> >::put(char)@plt>
      400903:   5b                      pop    %rbx
      400904:   48 89 c7                mov    %rax,%rdi
      400907:   e9 74 fe ff ff          jmpq   400780 <std::basic_ostream<char, std::char_traits<char> >::flush()@plt>
      40090c:   0f 1f 40 00             nopl   0x0(%rax)
      400910:   48 89 df                mov    %rbx,%rdi
      400913:   e8 08 fe ff ff          callq  400720 <std::ctype<char>::_M_widen_init() const@plt>
      400918:   48 8b 03                mov    (%rbx),%rax
      40091b:   be 0a 00 00 00          mov    $0xa,%esi
      400920:   48 89 df                mov    %rbx,%rdi
      400923:   ff 50 30                callq  *0x30(%rax)
      400926:   eb ce                   jmp    4008f6 <foo(int, int, int)+0x36>
      400928:   e8 e3 fd ff ff          callq  400710 <std::__throw_bad_cast()@plt>
      40092d:   0f 1f 00                nopl   (%rax)
    
    0000000000400930 <test_lambda()>:
      400930:   53                      push   %rbx
      400931:   ba 04 00 00 00          mov    $0x4,%edx
      400936:   be 2c 0b 40 00          mov    $0x400b2c,%esi
      40093b:   bf 60 10 60 00          mov    $0x601060,%edi
      400940:   e8 2b fe ff ff          callq  400770 <std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)@plt>
      400945:   48 8b 05 14 07 20 00    mov    0x200714(%rip),%rax        # 601060 <std::cout@@GLIBCXX_3.4>
      40094c:   48 8b 40 e8             mov    -0x18(%rax),%rax
      400950:   48 8b 98 50 11 60 00    mov    0x601150(%rax),%rbx
      400957:   48 85 db                test   %rbx,%rbx
      40095a:   74 3c                   je     400998 <test_lambda()+0x68>
      40095c:   80 7b 38 00             cmpb   $0x0,0x38(%rbx)
      400960:   74 1e                   je     400980 <test_lambda()+0x50>
      400962:   0f b6 43 43             movzbl 0x43(%rbx),%eax
      400966:   bf 60 10 60 00          mov    $0x601060,%edi
      40096b:   0f be f0                movsbl %al,%esi
      40096e:   e8 1d fe ff ff          callq  400790 <std::basic_ostream<char, std::char_traits<char> >::put(char)@plt>
      400973:   5b                      pop    %rbx
      400974:   48 89 c7                mov    %rax,%rdi
      400977:   e9 04 fe ff ff          jmpq   400780 <std::basic_ostream<char, std::char_traits<char> >::flush()@plt>
      40097c:   0f 1f 40 00             nopl   0x0(%rax)
      400980:   48 89 df                mov    %rbx,%rdi
      400983:   e8 98 fd ff ff          callq  400720 <std::ctype<char>::_M_widen_init() const@plt>
      400988:   48 8b 03                mov    (%rbx),%rax
      40098b:   be 0a 00 00 00          mov    $0xa,%esi
      400990:   48 89 df                mov    %rbx,%rdi
      400993:   ff 50 30                callq  *0x30(%rax)
      400996:   eb ce                   jmp    400966 <test_lambda()+0x36>
      400998:   e8 73 fd ff ff          callq  400710 <std::__throw_bad_cast()@plt>
      40099d:   0f 1f 00                nopl   (%rax)
    
    00000000004009a0 <test_bind()>:
      4009a0:   ba 03 00 00 00          mov    $0x3,%edx
      4009a5:   be 02 00 00 00          mov    $0x2,%esi
      4009aa:   bf 01 00 00 00          mov    $0x1,%edi
      4009af:   e9 0c ff ff ff          jmpq   4008c0 <foo(int, int, int)>
      4009b4:   66 66 66 2e 0f 1f 84    data32 data32 nopw %cs:0x0(%rax,%rax,1)
      4009bb:   00 00 00 00 00 
    
    00000000004009c0 <test_lambda(int)>:
      4009c0:   53                      push   %rbx
      4009c1:   ba 04 00 00 00          mov    $0x4,%edx
      4009c6:   be 2c 0b 40 00          mov    $0x400b2c,%esi
      4009cb:   bf 60 10 60 00          mov    $0x601060,%edi
      4009d0:   e8 9b fd ff ff          callq  400770 <std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)@plt>
      4009d5:   48 8b 05 84 06 20 00    mov    0x200684(%rip),%rax        # 601060 <std::cout@@GLIBCXX_3.4>
      4009dc:   48 8b 40 e8             mov    -0x18(%rax),%rax
      4009e0:   48 8b 98 50 11 60 00    mov    0x601150(%rax),%rbx
      4009e7:   48 85 db                test   %rbx,%rbx
      4009ea:   74 3c                   je     400a28 <test_lambda(int)+0x68>
      4009ec:   80 7b 38 00             cmpb   $0x0,0x38(%rbx)
      4009f0:   74 1e                   je     400a10 <test_lambda(int)+0x50>
      4009f2:   0f b6 43 43             movzbl 0x43(%rbx),%eax
      4009f6:   bf 60 10 60 00          mov    $0x601060,%edi
      4009fb:   0f be f0                movsbl %al,%esi
      4009fe:   e8 8d fd ff ff          callq  400790 <std::basic_ostream<char, std::char_traits<char> >::put(char)@plt>
      400a03:   5b                      pop    %rbx
      400a04:   48 89 c7                mov    %rax,%rdi
      400a07:   e9 74 fd ff ff          jmpq   400780 <std::basic_ostream<char, std::char_traits<char> >::flush()@plt>
      400a0c:   0f 1f 40 00             nopl   0x0(%rax)
      400a10:   48 89 df                mov    %rbx,%rdi
      400a13:   e8 08 fd ff ff          callq  400720 <std::ctype<char>::_M_widen_init() const@plt>
      400a18:   48 8b 03                mov    (%rbx),%rax
      400a1b:   be 0a 00 00 00          mov    $0xa,%esi
      400a20:   48 89 df                mov    %rbx,%rdi
      400a23:   ff 50 30                callq  *0x30(%rax)
      400a26:   eb ce                   jmp    4009f6 <test_lambda(int)+0x36>
      400a28:   e8 e3 fc ff ff          callq  400710 <std::__throw_bad_cast()@plt>
      400a2d:   0f 1f 00                nopl   (%rax)
    
    0000000000400a30 <test_bind(int)>:
      400a30:   ba 03 00 00 00          mov    $0x3,%edx
      400a35:   be 02 00 00 00          mov    $0x2,%esi
      400a3a:   e9 81 fe ff ff          jmpq   4008c0 <foo(int, int, int)>
      400a3f:   90                      nop
    

    Out of curiosity, I redid the test using GCC 4.7, and found that with 4.7, both tests were inlined in the same manner.

    My conclusion is that the performance should be the same in either case, but you might want to check your compiler output if it matters.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

This is a very open question about a problem that we have. Basically, we
This is basically a question about the lifetime of temporaries. If a function returns
I have a simple question about creating multiple initialisers within an objective-c class. Basically
Basically this is a follow up of this question about most vexing parse. I
I read a similar question about this that suggested using git log --graph --all
This is basically a very noob question about Ruby console (IRB), but I couldn't
This is basically the same question as Click items in select box, and then
This is basically a duplicate of this question , but the accepted answer was
Basically this is a question how to access local scope handler. I trying to
Basically the question is how to get from this: foo_id foo_name 1 A 1

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.