c++ 11学习笔记--Lambda 表达式(对比测试Lambda ,bind,Function Object)

所有c++ coder都应该为这个语法感到高兴,说的直白一点,Lambda 表达式就是函数对象的语法糖。

还是直接看对比栗子吧,抄袭的是msdn的官网

该示例使用 for_each 函数调用中嵌入的 lambda 向控制台打印 vector 对象中的每个元素是偶数还是奇数。

使用lambda

#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

int main()
{
   // Create a vector object that contains 10 elements.
   vector<int> v;
   for (int i = 0; i < 10; ++i) {
      v.push_back(i);
   }

   // Count the number of even numbers in the vector by
   // using the for_each function and a lambda.
   int evenCount = 0;
   for_each(v.begin(), v.end(),[&evenCount] (int n) {
      cout << n;
      if (n % 2 == 0) {
         cout << " is even " << endl;
         ++evenCount;
      } else {
         cout << " is odd " << endl;
      }
   });

   // Print the count of even numbers to the console.
   cout << "There are " << evenCount
        << " even numbers in the vector." << endl;
}

使用Function Object

#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

class FunctorClass
{
public:
    // The required constructor for this example.
    explicit FunctorClass(int& evenCount)
        : m_evenCount(evenCount)
    {
    }

    // The function-call operator prints whether the number is
    // even or odd. If the number is even, this method updates
    // the counter.
    void operator()(int n) const
    {
        cout << n;

        if (n % 2 == 0) {
            cout << " is even " << endl;
            ++m_evenCount;
        } else {
            cout << " is odd " << endl;
        }
    }

private:
    // Default assignment operator to silence warning C4512.
    FunctorClass& operator=(const FunctorClass&);

    int& m_evenCount; // the number of even variables in the vector.
};

int main()
{
    // Create a vector object that contains 10 elements.
    vector<int> v;
    for (int i = 0; i < 10; ++i) {
        v.push_back(i);
    }

    // Count the number of even numbers in the vector by
    // using the for_each function and a function object.
    int evenCount = 0;
    for_each(v.begin(), v.end(), FunctorClass(evenCount));

    // Print the count of even numbers to the console.
    cout << "There are " << evenCount
        << " even numbers in the vector." << endl;
}

正如微软文档所言,这两种在效率上并没有实质性的差距,我自己也测试了,不管在debug模式下还是release模式下,果然没有差距。

无意中我在晚上发现了bind和Lambda对比测试,前三种方式是网上的,后面两种是我自己加的,结果绝对让我蛋碎了一地。

#include <cstdint>
#include <chrono>
#include <iostream>
#include <string>
#include <thread>
#include <vector>
#include <algorithm>

#if USE_BOOST
#include <boost/function.hpp>
#include <boost/bind.hpp>
#endif

class FunctorClass
{
public:
    // The required constructor for this example.
    explicit FunctorClass(uint64_t& evenCount)
    : m_evenCount(evenCount)
    {
    }

    // The function-call operator prints whether the number is
    // even or odd. If the number is even, this method updates
    // the counter.
    void operator()(int n) const
    {
         m_evenCount += n;
    }

private:
    // Default assignment operator to silence warning C4512.
    FunctorClass& operator=(const FunctorClass&);

    uint64_t& m_evenCount; // the number of even variables in the vector.
};

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 = 100000000ULL)
{
    uint64_t i;
    for (i = 0; i < upper_limit; ++i)
        func(i);
    if(i == upper_limit)
    {
        std::cout<<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;
}

uint64_t test_accumulate_class_function()
{
    uint64_t x = 0;

    do_test_loop(FunctorClass(x));
   // for_each(v.begin(), v.end(), FunctorClass(x));
    return x;
}

uint64_t test_accumulate_bind_auto()
{
    namespace arg = std::placeholders;

    uint64_t x = 0;
    auto accumulator = std::bind(&test_accumulate_bind_function, std::ref(x), arg::_1);
    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);
    run_test("Accumulate (Function Object)    ", &test_accumulate_class_function);
    run_test("Accumulate (bind auto)    ", &test_accumulate_bind_auto);
#if USE_BOOST
    run_test("Accumulate (boost bind)        ", &test_accumulate_boost_bind);
    run_test("Accumulate (boost bound lambda)", &test_accumulate_bound_lambda);
#endif
}

debug模式:

Accumulate (lambda)            100000000  422885105

Accumulate (bind)              100000000   4346676523

Accumulate (bound lambda)      100000000 1707092933

Accumulate (class function)    100000000   494674507

Accumulate (bind auto)         100000000 3381097610

 

Release模式

Accumulate (lambda)            100000000  17978

Accumulate (bind)              100000000   607188485

Accumulate (bound lambda)      100000000 520421500

Accumulate (Function Object)    100000000  1925

Accumulate (bind auto)         100000000 1726

编译器:APPLE LLVM5.1

c++就是这样让人蛋疼,随便一个东西,初学者都可以写5中写法,那大神下,至少可以写10种以上,效率上的差距也是大的惊人,我还是那句话c++应该做减法了。

c++ 11学习笔记--Lambda 表达式(对比测试Lambda ,bind,Function Object)

时间: 2024-12-24 10:00:30

c++ 11学习笔记--Lambda 表达式(对比测试Lambda ,bind,Function Object)的相关文章

c++ 11学习笔记-- 常量表达式(constexpr)

最新在弄android ndk相关的,惊奇的发现最新的ndk10的版本已经gcc4.9了,我印象中,gcc4.8就支持C++0x11,14的支持,gcc再次走到了llvm的前面,LLVM最新的版本3.4.2应该只支持c++ 11,如果是同样的c++代码我一直认为llvm的效率会明显强过gcc. 废话不多说,让我们开始学习c++ 11吧,说实话我之前一直都很抗拒c++新的语法,感觉太难接受了,现在看来不熟悉也不行了. 常量表达式(constexpr) 常量表达式机制是为了: 提供了更多的通用的值不

Derby-10.11学习笔记汇总

鲁春利的工作笔记,谁说程序员不能有文艺范? Derby-10.11学习笔记(一)简单介绍 http://luchunli.blog.51cto.com/2368057/1716255 Derby-10.11学习笔记(二)脚本介绍 http://luchunli.blog.51cto.com/2368057/1716464 Derby-10.11学习笔记(三)

C#3.0之神奇的Lambda表达式和Lambda语句

“Lambda 表达式”是一个匿名函数,它可以包含表达式和语句,并且可用于创建委托或表达式目录树类型.所有 Lambda 表达式都使用 Lambda 运算符 =>,该运算符读为“goes to”.该 Lambda 运算符的左边是输入参数(如果有),右边包含表达式或语句块.Lambda 表达式 x => x * x 读作“x goes to x times x”.可以将此表达式分配给委托类型. 表达式在右边的 Lambda 表达式称为“Lambda 表达式”. Lambda 表达式在构造表达式目

802.11 学习笔记

一.网络服务 802 . 11 总共提供 9 种服务: 分布式 ( distribution ) 接入点收到帧 , 就会使用分布式服务将真传送至目的地. 整合 ( integration ) 该服务由分布式系统提供,它让分布式系统得以链接至非 IEEE802.11 网络 关联( association ) 移动式工作站向接入点登记,分布式系统就可以依据登记信息推断哪个移动式工作站该使用哪个接入点.仅仅有关联之后才干进行身份验证.在身份验证完毕之前,接入点会丢弃来自工作站的全部数据. 又一次关联(

C#中分别对委托、匿名方法、Lambda表达式、Lambda表达式树以及反射执行同一方法的过程进行比较。

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Reflection; using System.Linq.Expressions; namespace INPEXOne.LearnCS { class RefletLambdaDelegate { static object[] para

c++ 11学习笔记--智能指针

C++ 98的 std::auto_ptr已经被彻底遗弃了,取而代之的是unique_ptr.shared_ptr与weak_ptr.大部分时候我们自己手动申请内存方式内存都是没有问题的,问题是如果程序很大了之后,一个复杂的对象,多次拷贝的代价非常高,很多地方都会使用到,只存在一份拷贝显然是最好的,这个时候对象生命周期的管理就会很复杂,所以c++引入了智能指针. 任何事物都会有两面性. Shared_ptr 摘录于Effective C++, 3rd Edition, Item 17: 在 st

LINQ学习笔记——(2)Lambda表达式

最基本的 Lambda 表达式语法: (参数列表)=>{方法体} 说明: 参数列表中的参数类型可以是明确类型或者是推断类型 如果是推断类型,则参数的数据类型将由编译器根据上下文自动推断出来 class Program { public delegate string trans(string s); static void Main(string[] args) { string s = "abcdEFGH"; trans tran = (string str) => {

C++ 11 Lambda表达式、auto、function、bind、final、override

接触了cocos2dx 3.0,就必须得看C++ 11了.有分享过帖子:[转帖]漫话C++0x(四) —- function, bind和lambda.其实最后的Lambda没太怎么看懂. 看不懂没关系,会用就行.可惜是连用都要思考半天.其实,查找根源是定义没有搞明白. 以后买东西,用之前,先看说明书才是必要的. ---------------------------------开始正文粘贴----------------------------------------- 一.Lambda表达式

Python学习笔记010——匿名函数lambda

1 语法 my_lambda = lambda arg1, arg2 : arg1 + arg2 + 1 arg1.arg2:参数 arg1 + arg2 + 1 :表达式 2 描述 匿名函数不需要return来返回值,表达式本身结果就是返回值. lambda 仅简洁了代码,并不会提高程序运行效率 如果可以用 for...in...if 来完成的,最好不使用匿名函数lambda 使用lambda时,函数内不要包含循环.嵌套:如果存在,则最好使用def函数来完成,这样的代码可读性和复用性均较高 l