[위 에] C + + Pirate: Lambda vs Bind
16927 단어 lambda
전재 출처 설명:http://blog.csdn.net/cywosp/article/details/9379403
먼저 아래 함 수 를 보 여 주세요.
template <typename Function>
void do_test_loop(Function func, const uint64_t upper_limit = 1000000000ULL)
{
for (uint64_t i = 0; i < upper_limit; ++i)
func(i);
}
func upper_limit( 10 ) 。 func , :
1. std::bind std::function<void (uint64_t)> 。
2.lambda
void test_accumulate_bind_function(uint64_t& x, uint64_t i)
{
x += i;
}
uint64_t test_accumulate_bind()
{
namespace arg = std::placeholders;
uint64_t x = 0;
std::function<void (uint64_t)> accumulator = std::bind(&test_accumulate_bind_function, std::ref(x), arg::_1);
do_test_loop(accumulator);
return x;
}
, boost::bind , , 。 , , ( ), 。
lambda :
uint64_t test_accumulate_lambda()
{
uint64_t x = 0;
auto accumulator = [&x] (uint64_t i) { x += i; };
do_test_loop(accumulator);
return x;
}
lambda 。 , std::function 。lambda , auto 。 accumulator lambda ( lambda )。 。 do_test_loop cpp , lambda 。 , , lambda std::function , :
uint64_t test_accumulate_bound_lambda()
{
uint64_t x = 0;
std::function<void (uint64_t)> accumulator = [&x] (uint64_t i) { x += i; };
do_test_loop(accumulator);
return x;
}
lambda std::bind, std::function C++ lambda 。 。
( timer ):
template <typename Function>
void run_test(const std::string& name, Function func)
{
std::cout << name;
timer t;
volatile_write(func());
timer::duration duration = t.elapsed();
std::cout << '\t' << duration.count() << std::endl;
}
int main()
{
run_test("Accumulate (lambda) ", &test_accumulate_lambda);
run_test("Accumulate (bind) ", &test_accumulate_bind);
run_test("Accumulate (bound lambda)", &test_accumulate_bound_lambda);
}
, gcc 4.4.2 -O3 Inter Core i7 Q740 :
Accumulate (lambda) 7 Accumulate (bind) 4401849 Accumulate (bound lambda) 4379315
。
(gdb) disassemble test_accumulate_lambda Dump of assembler code for function _Z22test_accumulate_lambdav: 0x0000000000400e70 <+0>: movabs $0x6f05b59b5e49b00,%rax 0x0000000000400e75 <+5>: retq End of assembler dump.
, 0x6f05b59b5e49b00( :499999999500000000) rax 。 0 1000000000 , 。 do_test_loop , :
uint64_t test_accumulate_lambda()
{
uint64_t x = 0;
// do_test_loop:
for (uint64_t i = 0; i < 1000000000; ++i)
x += i;
return x;
}
。 : lambda , lambda 。 std::function ? , do_test_loop std::function<void (uint64_t)> , func , ( std::function )。std::bind lambda 。 , lambda std::bind , 。 , std::reference_wrapper 。 。
std::bind #0 test_accumulate_bind_function (x=@0x7fffffffe5d0, i=0) at lambda_vs_bind.cpp:106 #1 0x0000000000401111 in operator() (__args#0=0, this=<optimized out>) at /usr/local/include/gcc-4.6.2/functional:2161 #2 do_test_loop<std::function<void(long unsigned int)> > (func=<optimized out>, upper_limit=<optimized out>) at lambda_vs_bind.cpp:93 #3 test_accumulate_bind () at lambda_vs_bind.cpp:115 #4 0x0000000000401304 in run_test<unsigned long (*)()> (name=<optimized out>, func=0x401080 <test_accumulate_bind()>) at lambda_vs_bind.cpp:84 #5 0x0000000000401411 in main () at lambda_vs_bind.cpp:136
Lambda Expression #0 std::_Function_handler<void(long unsigned int), test_accumulate_bound_lambda()::<lambda(uint64_t)> >::_M_invoke(const std::_Any_data &, unsigned long) (__functor=..., __args#0=0) at /usr/local/include/gcc-4.6.2/functional:1778 #1 0x0000000000400fa9 in operator() (__args#0=0, this=<optimized out> at /usr/local/include/gcc-4.6.2/functional:2161 #2 do_test_loop<std::function<void(long unsigned int)> > (func=<optimized out>, upper_limit=<optimized out>) at lambda_vs_bind.cpp:93 #3 test_accumulate_bound_lambda () at lambda_vs_bind.cpp:126 #4 0x0000000000401304 in run_test<unsigned long (*)()> (name=<optimized out>, func=0x400f20 <test_accumulate_bound_lambda()>) at lambda_vs_bind.cpp:84 #5 0x000000000040143e in main () at lambda_vs_bind.cpp:140
std::function operator() , , g++ 4.6.2 std::function :
template<typename _Res, typename... _ArgTypes>
class function<_Res(_ArgTypes...)>
: public _Maybe_unary_or_binary_function<_Res, _ArgTypes...>,
private _Function_base
{
// a whole bunch of implementation details
private:
typedef _Res (*_Invoker_type)(const _Any_data&, _ArgTypes...);
_Invoker_type _M_invoker;
};
std::function virtual 。 , std::function —— 。
boost:bind
boost::bind ? , boost std。
Accumulate (boost bind) 3223174 Accumulate (boost bound lambda) 4255098
boost::bind std::bind 25% ,boost::bind std::bind :
#0 test_accumulate_bind_function (x=@0x7fffffffe600, i=0) at lambda_vs_bind.cpp:114 #1 0x00000000004018a3 in operator() (a0=0, this=<optimized out>) at /usr/local/include/boost/function/function_template.hpp:1013 #2 do_test_loop<boost::function<void(long unsigned int)> > (upper_limit=<optimized out>, func=<optimized out>) at lambda_vs_bind.cpp:101 #3 test_accumulate_boost_bind () at lambda_vs_bind.cpp:144 #4 0x0000000000401f44 in run_test<unsigned long (*)()> (name=<optimized out>, func=0x401800 <test_accumulate_boost_bind()>) at lambda_vs_bind.cpp:92 #5 0x000000000040207e in main () at lambda_vs_bind.cpp:161
( boost::bind std::bind ... ...)
functional
template<typename _Functor, typename... _ArgTypes>
inline
typename _Bind_helper<_Functor, _ArgTypes...>::type
bind(_Functor&& __f, _ArgTypes&&... __args)
{
typedef _Bind_helper<_Functor, _ArgTypes...> __helper_type;
typedef typename __helper_type::__maybe_type __maybe_type;
typedef typename __helper_type::type __result_type;
return __result_type(__maybe_type::__do_wrap(std::forward<_Functor>(__f)),
std::forward<_ArgTypes>(__args)...);
}
boost/bind/bind.hpp (with the macros expanded)
template<class F, class A1, class A2>
_bi::bind_t<_bi::unspecified, F, typename _bi::list_av_2<A1, A2>::type>
bind(F f, A1 a1, A2 a2)
{
typedef typename _bi::list_av_2<A1, A2>::type list_type;
return _bi::bind_t<_bi::unspecified, F, list_type> (f, list_type(a1, a2));
}
1.
http://www.gockelhut.com/c++/files/lambda_vs_bind.cpp。 g++ 4.6.2 , c++11 。 Boost 1.47, , boost::bind ( )。 boost, USE_BOOST 0 。
2. volatile_write
volatile_write 함 수 는 시스템 이 메모리 에 데 이 터 를 쓰 도록 강제 하 는 간단 한 함수 입 니 다. 그러면 최적화 기 가 함수 run 을 최적화 하 는 것 을 방지 할 수 있 습 니 다.test 에는 아무것도 할 코드 가 없습니다.
template <typename T>
void volatile_write(const T& x)
{
volatile T* p = new T;
*p = x;
delete p;
}
:http://www.gockelhut.com/c++/articles/lambda_vs_bind
lambda_vs_bind.cpp
/**
* Copyright 2011 Travis Gockel
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
// Turn building and testing boost::bind on or off with this macro
#define USE_BOOST 1
// workaround for varieties of g++-4.6 with --std=gnu++0x
#ifndef _GLIBCXX_USE_NANOSLEEP
# define _GLIBCXX_USE_NANOSLEEP
#endif
#include <cstdint>
#include <chrono>
#include <iostream>
#include <string>
#include <thread>
#if USE_BOOST
#include <boost/function.hpp>
#include <boost/bind.hpp>
#endif
class timer
{
public:
typedef std::chrono::high_resolution_clock clock;
typedef clock::time_point time_point;
typedef clock::duration duration;
public:
timer()
{
reset();
}
void reset()
{
_starttime = clock::now();
}
duration elapsed() const
{
return clock::now() - _starttime;
}
protected:
time_point _starttime;
};
bool test_timer()
{
using std::chrono::milliseconds;
typedef timer::duration duration;
const milliseconds sleep_time(500);
timer t;
std::this_thread::sleep_for(sleep_time);
duration recorded = t.elapsed();
// make sure the clock and this_thread::sleep_for is precise within one millisecond (or at least in agreement as to
// how inaccurate they are)
return (recorded - milliseconds(1) < sleep_time)
&& (recorded + milliseconds(1) > sleep_time);
}
template <typename T>
void volatile_write(const T& x)
{
volatile T* p = new T;
*p = x;
delete p;
}
template <typename Function>
void run_test(const std::string& name, Function func)
{
std::cout << name;
timer t;
volatile_write(func());
timer::duration duration = t.elapsed();
std::cout << '\t' << duration.count() << std::endl;
}
template <typename Function>
void do_test_loop(Function func, const uint64_t upper_limit = 1000000000ULL)
{
for (uint64_t i = 0; i < upper_limit; ++i)
func(i);
}
uint64_t test_accumulate_lambda()
{
uint64_t x = 0;
auto accumulator = [&x] (uint64_t i) { x += i; };
do_test_loop(accumulator);
return x;
}
void test_accumulate_bind_function(uint64_t& x, uint64_t i)
{
x += i;
}
uint64_t test_accumulate_bind()
{
namespace arg = std::placeholders;
uint64_t x = 0;
std::function<void (uint64_t)> accumulator = std::bind(&test_accumulate_bind_function, std::ref(x), arg::_1);
do_test_loop(accumulator);
return x;
}
uint64_t test_accumulate_bound_lambda()
{
uint64_t x = 0;
std::function<void (uint64_t)> accumulator = [&x] (uint64_t i) { x += i; };
do_test_loop(accumulator);
return x;
}
#if USE_BOOST
uint64_t test_accumulate_boost_bind()
{
uint64_t x = 0;
boost::function<void (uint64_t)> accumulator = boost::bind(&test_accumulate_bind_function, boost::ref(x), _1);
do_test_loop(accumulator);
return x;
}
uint64_t test_accumulate_boost_bound_lambda()
{
uint64_t x = 0;
boost::function<void (uint64_t)> accumulator = [&x] (uint64_t i) { x += i; };
do_test_loop(accumulator);
return x;
}
#endif
int main()
{
if (!test_timer())
{
std::cout << "Failed timer test." << std::endl;
return -1;
}
run_test("Accumulate (lambda) ", &test_accumulate_lambda);
run_test("Accumulate (bind) ", &test_accumulate_bind);
run_test("Accumulate (bound lambda) ", &test_accumulate_bound_lambda);
#if USE_BOOST
run_test("Accumulate (boost bind) ", &test_accumulate_boost_bind);
run_test("Accumulate (boost bound lambda)", &test_accumulate_bound_lambda);
#endif
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Lambda Cron 예제(Terraform)이 기사에서는 EventBridge를 사용하여 일정에 따라 람다를 트리거하는 방법을 살펴보겠습니다. Terraform을 사용하여 이를 구현할 것입니다. 이 예제에서는 간단한 Golang Hello World 예제를 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.