SORU
2 EKİM 2011, Pazar


C 11: lambda ifadesi nedir?

C 11: lambda ifadesi nedir? Ne zaman kullanmalıyım? Ne sınıf sorun bunların olası giriş önce değildi çözer mi?

Birkaç örnek ve durumlarda kullanmak faydalı olacaktır.

CEVAP
2 EKİM 2011, Pazar


Sorun

C std::for_each ve çok kullanışlı olabilir std::transform, jenerik gibi yararlı fonksiyonları içerir. Ne yazık ki, özellikle de eğer uygulamak istiyorum functor belirli bir işlevi için eşsiz ise kullanmak için oldukça hantal olabilir.

#include <algorithm>
#include <vector>

namespace {
  struct f {
    void operator()(int) {
      // do something
    }
  };
}

void func(std::vector<int>& v) {
  f f;
  std::for_each(v.begin(), v.end(), f);
}

Eğer sadece f Bir kez ve belirli bir yerde kullanırsanız abartılı bir şey önemsiz ve bir bütün sınıf yazılı kapalı gibi görünüyor.

C 03 aşağıdaki gibi, eşleme yerel tutmak için yazmak için cazip olabilir:

void func2(std::vector<int>& v) {
  struct {
    void operator()(int) {
       // do something
    }
  } f;
  std::for_each(v.begin(), v.end(), f);
}

ancak bu, f C 03 şablon işlev geçirilemez izin verilmez.

Yeni çözüm

C Lambda 11 struct f yerine satır içi, isimsiz bir functor yazmak için izin tanıttı. Küçük, basit bir örnek için bu korumak için okumak için daha temiz (bir yerde her şey tutar) ve potansiyel olarak daha basit, en basit şekliyle, örneğin:

void func3(std::vector<int>& v) {
  std::for_each(v.begin(), v.end(), [](int) { /* do something here*/ });
}

Lambda fonksiyonları sadece anonim funktorlar için sözdizimsel şeker.

Türlerini döndürür

Basit durumlarda dönüş lambda yazın, örneğin için birebir:

void func4(std::vector<double>& v) {
  std::transform(v.begin(), v.end(), v.begin(),
                 [](double d) { return d < 0.00001 ? 0 : d; }
                 );
}

dönüş türü olamaz derleyici tarafından kurtuldu hızla durumlarda karşılaşacağınız daha karmaşık Lambda yazmaya başladığınızda ancak, örneğin:

void func4(std::vector<double>& v) {
    std::transform(v.begin(), v.end(), v.begin(),
        [](double d) {
            if (d < 0.0001) {
                return 0;
            } else {
                return d;
            }
        });
}

Bu sorunu çözmek için açıkça lambda fonksiyon dönüş türü, -> T kullanarak belirtmek için izin verilir:

void func4(std::vector<double>& v) {
    std::transform(v.begin(), v.end(), v.begin(),
        [](double d) -> double {
            if (d < 0.0001) {
                return 0;
            } else {
                return d;
            }
        });
}

"Yakalama" değişkenleri

Şimdiye kadar hiçbir şey içindeki lambda geçti neydi dışında değil kullandık, ama aynı zamanda diğer değişkenler kullanabiliriz, lambda içinde. Eğer diğer değişkenleri erişmek istiyorsanız, şimdiye kadar bu örneklerde kullanılmamış olan yakalama maddesinin (ifade []), örneğin kullanabilirsiniz:

void func5(std::vector<double>& v, const double& epsilon) {
    std::transform(v.begin(), v.end(), v.begin(),
        [epsilon](double d) -> double {
            if (d < epsilon) {
                return 0;
            } else {
                return d;
            }
        });
}

= & kullanarak belirtebilirsiniz iki referans ve değer ile çekebilirsiniz:

  • [&epsilon] referans ve yakalar
  • [&, epsilon] yakalama varsayılan şekilde fotoğraf çekmek istediğimizi başvuru ve olduğunu belirtin
  • [=, &epsilon] epsilon varsayılan olarak, ama değeri referans yerine yakalama kullanın

operator() const yakalar bunları varsayılan olarak erişim const olacağını ima ile varsayılan olarak oluşturulur. Bu, her biri aynı sonucu üretecektir aynı giriş yapabilir, ancak mark the lambda as mutable üretilen operator() const değil istemek için çağrı etkiye sahiptir.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • GUN-TIME with Brandon

    GUN-TIME wit

    3 ŞUBAT 2009
  • PhoneBuff

    PhoneBuff

    10 HAZİRAN 2011
  • wwjoshdew

    wwjoshdew

    1 AĞUSTOS 2007