2012-02-15 10 views
6

this one gibi SO üzerinde bazı iyi örnekleyiciler buldum ve tüm inandırıcı örnekler, operator()'u tanımlayan sınıftaki durumu kullanıyor gibi görünüyor.Bu stateless sınıfı bir işlev çağrısı operatörü ile bir c stili işleviyle mi kullanacak?

İşlev çağrısı operatörünü durum bilgisi olmadan tanımlayan bir kitaptaki bir örnekle karşılaştım ve bunu yapamayacağımı düşünüyorum, ancak bunun garip bir kullanım olduğunu ve normal stil işlevi işaretçisinin kullanmaktan daha iyi olacağını operator() burada her şekilde - daha az kod, daha az değişkenler (karşılaştırıcıları örneklendirmelisiniz), muhtemelen daha verimli olması ve anlam kaybı ya da kapsülleme olmaması (sadece tek bir fonksiyon olduğu için).

Biliyorum std::sortoperator() sınıfları ve işlevleri arasında seçim yapmanıza izin verir, ancak yukarıdaki mantık nedeniyle işlevleri her zaman kullandım.

Bir sınıfın tercih edilmesinin nedenleri nelerdir? İşte

örnek (aktarılan) var:

class Point2D { 
    //.. accessors, constructors 
    int x,y; 
}; 
class HorizComp { 
public: 
    bool operator()(const Point2D& p, const Point2D& q) const 
    { return p.getX() < q.getX(); } 
}; 

class VertComp { 
public: 
    bool operator()(const Point2D& p, const Point2D& q) const 
    { return p.getY() < q.getY(); } 
}; 

template <typename E, typename C> 
void printSmaller(const E& p, const E& q, const C& isLess) { 
    cout << (isLess(p, q) ? p : q) << endl; // print the smaller of p and q 
} 
//... 
// usage in some function: 
Point2D p(1.2, 3.2), q(1.5, 9.2); 
HorizComp horizComp; 
VertComp vorizComp; 
printSmaller(p, q, horizComp); 
printSmaller(p, q, vorizComp); 

cevap

8

tipik nedeni Bunu yaparken şudur:

bool(const Point&,const Point&) 
:

bool less_than(const Point&, const Point&); 
// ... 
std::sort(..., &less_than); 

dayanağı için şablon argümanı şudur

Sıralama işlevi bir işlev işaretçisi aldığından, derleyici için daha zor std::sort() içinde yüklemeyi kullanmak için. Başka bir işlevi std::sort() instatiation iki yüklemler arasında paylaşılabilir olur, yani aynı türe sahip

bool greater_than(const Point&, const Point&); 

olabilir çünkü bu olur. ('u'u daha zor hale getirdiğini, imkansız olmadığını söylediğimi hatırla). Buna karşılık

, bunu yaptığında bu:

struct less_than { 
    bool operator()(const Point&, const Point&) const; 
}; 
// ... 
std::sort(..., less_than()); 


struct greater_than { 
    bool operator()(const Point&, const Point&) const; 
}; 
// ... 
std::sort(..., greater_than()); 

derleyici daha kolay yüklem tanımına satır içi için yapım her dayanağı için std::sort() için benzersiz şablon örnekleme üretir.

+0

Serin:

struct Cmp2 { bool operator()(const shared_ptr<X>& left, const string& right) const { return left->name < right; } bool operator()(const string& left, const shared_ptr<X>& right) const { return left < right->name; } }; 

Bu bize bir string adı nesnesi ile equal_range olabilmesinin önünü: equal_range çalışmak için yüklem iki farklı karşılaştırma fonksiyonları sahip olması gerekir. Eylemdeki satır içi performansını gösteren bir blog yazısı buldum: http://codeforthought.blogspot.com/2011/07/performance-functors-vs-functions.html –

+0

Bunu bir derleyici sorunu olarak gördüğümü itiraf etmeliyim. Inlining ile benzer sorunları gördüm ve derleyici aramaları sonuç olarak sanallaştırmayı başaramadı. Bana öyle görünüyor ki, bu, parıldayan sabit bir yayılmanın başarması gereken bir şeydir (bu durumda, 'less_than'ın tanımı görünür olduğu sürece). –

+0

@MatthieuM .: Kesinlikle bir derleyici sorunudur. Bu yüzden "daha zor", "daha kolay", vb. Terimleri kullandım. Derleyicinin * hem yüklemler için hem de işlevler olarak ayrı ayrı anlık oluşumlar oluşturmayacakları ve hala kendi bedenlerini inline etmelerinin temel bir nedeni yok. Sadece pratik nedenlerden dolayı derleyici uygulayıcıları bu durum için özel bir durum (henüz) yapmış olmayabilir. –

5

Bir neden çalışma zamanı verimliliği. Bir işleve bir gösterici iletirseniz, derleyici bu işlev için satır içi üretmek için alışılmadık derecede akıllı olmalıdır. operator()'u tanımlayan bir nesneyi geçmek, derleyici kod satır içi üretmek için çok kolaylaştırır. Özellikle sıralama gibi bir şey için, bu hızı oldukça arttırabilir.

C++ 11'de, bir sınıfın kullanılmasının bir başka nedeni, kolaylık sağlamak içindir - sınıfı tanımlamak için bir lambda ifadesi kullanabilirsiniz.

0

Diğerleri, derleyicinin çeviriciyi satır içi tutma yeteneği hakkında iyi notlar yaptı. Functor nesnelerinin ve fonksiyon işaretçilerinin bir başka olasılık avantajı esnekliktir. Funtor bir şablon olabilir, belki türetilmiş bir sınıf olabilir, belki de zaman konfigürasyonuna sahiptir (zaman operatöründe vatansız olsa bile) (vs.)

0

Diğer bir neden bazen bir karşılaştırma fonksiyonunun yeterli olmamasıdır.Biz sort fonksiyon için kendi yüklemi tanımlamak zorunda biz name tarafından vektörü sıralamak istiyorsanız Şimdi

struct X { string name; }; 
vector<shared_ptr<X>> v; 

: en pointerın bir vektör var diyelim

struct Cmp1 
{ 
    bool operator()(const shared_ptr<X>& left, const shared_ptr<X>& right) const 
    { return left->name < right->name; } 
}; 

güzel ama Belirli bir isimle nesneleri bulmamız gerektiğinde ne yaparız? Bunu düşünmek vermedi

equal_range(v.begin(), v.end(), name, Cmp2()) 
İlgili konular