Uygulaması, std::function
bir uygulamadan diğerine farklılık gösterebilir, ancak temel fikir, tür silmeyi kullanmasıdır. Bunu yapmanın birden fazla yolu olsa da, önemsiz (optimal olmayan) bir çözümün şöyle olabileceğini hayal edebilirsiniz std::function<int (double)>
(basitlik uğruna belirli bir durum için basitleştirilmiştir):
struct callable_base {
virtual int operator()(double d) = 0;
virtual ~callable_base() {}
};
template <typename F>
struct callable : callable_base {
F functor;
callable(F functor) : functor(functor) {}
virtual int operator()(double d) { return functor(d); }
};
class function_int_double {
std::unique_ptr<callable_base> c;
public:
template <typename F>
function(F f) {
c.reset(new callable<F>(f));
}
int operator()(double d) { return c(d); }
};
Bu basit yaklaşımda, function
nesne sadece unique_ptr
bir taban tipini depolayacaktır . İle kullanılan her farklı işlev için function
, temelden türetilen yeni bir tür oluşturulur ve bu türden bir nesne dinamik olarak başlatılır. std::function
Nesne her zaman aynı boyutta ve yığın içinde farklı functors için gereken alanı tahsis edecektir.
Gerçek hayatta, performans avantajları sağlayan ancak yanıtı karmaşıklaştıracak farklı optimizasyonlar vardır. Tür, küçük nesne optimizasyonlarını kullanabilir, dinamik gönderim, bir düzey dolaylı yoldan kaçınmak için functor'u argüman olarak alan serbest işlevli bir işaretçi ile değiştirilebilir ... ancak fikir temelde aynıdır.
Kopyalarının nasıl std::function
davrandığı konusuyla ilgili olarak, hızlı bir test, durumu paylaşmak yerine dahili çağrılabilir nesnenin kopyalarının yapıldığını gösterir.
int main() {
int value = 5;
typedef std::function<void()> fun;
fun f1 = [=]() mutable { std::cout << value++ << '\n' };
fun f2 = f1;
f1();
fun f3 = f1;
f2();
f3();
}
Test, f2
bir referans yerine çağrılabilir varlığın bir kopyasını aldığını gösterir . Çağrılabilir varlık farklı std::function<>
nesneler tarafından paylaşılmış olsaydı, programın çıktısı 5, 6, 7 olurdu.
std::function
Bir süre önce gcc / stdlib uygulamasına baktım . Esasen bir polimorfik nesne için bir tutamaç sınıfıdır. Yığın üzerinde ayrılan parametreleri tutmak için dahili temel sınıfın türetilmiş bir sınıfı yaratılır - daha sonra buna işaretçi, öğesinin bir alt nesnesi olarak tutulurstd::function
.std::shared_ptr
Kopyalama ve taşıma gibi referans sayma yöntemini kullandığına inanıyorum .