Kutsuttavien olioiden valinta
Lambdat, bind vai osoittimet
Kutsuttavien olioiden valinta on ilmainen C++ Academy-oppitunti CoddyKitissä. Tämä on oppitunti 4/4. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu C++ Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. C++ Academy-kurssilla on yhteensä 4 oppituntia.
Kutsuttavien työkalupakki
C++ tarjoaa useita tapoja välittää toiminnallisuutta: funktio-osoittimet, lambdat, funktorit, std::bind-kutsun ja std::function-tyypin. Kukin sopii erilaisiin tarpeisiin.
- Yleinen kompromissi on nopeuden ja joustavuuden välillä.
- Myös luettavuudella on merkitystä.
#include <iostream>
int twice(int x) { return x * 2; }
int main() {
int (*fp)(int) = twice;
auto lam = [](int x) { return x * 2; };
std::cout << fp(5) << ' ' << lam(5) << '\n';
return 0;
}Milloin funktio-osoitinta kannattaa käyttää
Valitkaa funktio-osoitin, kun tarvitsette pienen, tilattoman takaisinkutsun ja haluatte C-yhteensopivuuden tai olemattomat lisäkustannukset.
#include <iostream>
void logMsg(const char* m) { std::cout << "LOG: " << m << '\n'; }
int main() {
void (*handler)(const char*) = logMsg;
handler("started");
return 0;
}Milloin lambdaa kannattaa käyttää
Lambda on moderni oletusvalinta: se on tiivis, voi kaapata tilaa, ja kääntäjä voi sijoittaa sen tehokkaasti suoraan koodiin malleissa ja algoritmeissa.
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> v = {3, 1, 4, 1, 5};
std::sort(v.begin(), v.end(), [](int a, int b) { return a > b; });
for (int x : v) std::cout << x << ' ';
std::cout << '\n';
return 0;
}Tilan kaappaaminen lambdassa
Lambda voi kaapata ympäröiviä muuttujia, toisin kuin funktio-osoitin, joten se sopii erinomaisesti kontekstia tarvitseviin takaisinkutsuihin.
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
int threshold = 3;
std::vector<int> v = {1, 2, 3, 4, 5};
int c = std::count_if(v.begin(), v.end(), [threshold](int x) { return x > threshold; });
std::cout << c << '\n';
return 0;
}Milloin funktoria kannattaa käyttää
Funktori (operator()-operaattorilla varustettu struct) sopii uudelleenkäytettävään, nimettyyn operaatioon, joka voi sisältää asetuksia ja jota käytetään monissa paikoissa.
#include <iostream>
#include <vector>
#include <algorithm>
struct AboveThreshold {
int limit;
bool operator()(int x) const { return x > limit; }
};
int main() {
std::vector<int> v = {1, 5, 2, 8};
std::cout << std::count_if(v.begin(), v.end(), AboveThreshold{4}) << '\n';
return 0;
}Lambda vai bind
Molemmilla voi esitäyttää argumentteja. Lambda on yleensä selkeämpi ja helpompi optimoida kääntäjälle, joten suosikaa sitä std::bind-toiminnon sijaan.
#include <iostream>
int power(int base, int exp) {
int r = 1;
for (int i = 0; i < exp; ++i) r *= base;
return r;
}
int main() {
auto square = [](int x) { return power(x, 2); };
std::cout << square(6) << '\n';
return 0;
}Milloin std::function-tyyppiä kannattaa käyttää
Käyttäkää std::function-tyyppiä, kun teidän on tallennettava kutsuttava olio, jonka konkreettista tyyppiä ei tunneta, esimerkiksi luokan jäsenenä tai säiliössä.
#include <iostream>
#include <functional>
#include <vector>
int main() {
std::vector<std::function<int(int)>> pipeline;
pipeline.push_back([](int x) { return x + 1; });
pipeline.push_back([](int x) { return x * 3; });
int v = 2;
for (auto& f : pipeline) v = f(v);
std::cout << v << '\n';
return 0;
}Mallit välttävät lisäkustannukset
Jos funktion tarvitsee vain vastaanottaa kutsuttava olio eikä tallentaa sitä, malliparametrin käyttö säilyttää täyden nopeuden välttämällä tyypin häivytystä.
#include <iostream>
template <typename F>
int applyTwice(int x, F f) { return f(f(x)); }
int main() {
std::cout << applyTwice(3, [](int n) { return n + 10; }) << '\n';
return 0;
}Suorituskykyjärjestys
Karkeasti järjestys on seuraava: mallipohjainen kutsuttava olio tai tilaton lambda on nopein, funktio-osoitin on lähes yhtä nopea, ja std::function hitain epäsuoran kutsun ja mahdollisen muistivarauksen vuoksi.
#include <iostream>
#include <functional>
int main() {
auto fast = [](int x) { return x + 1; };
std::function<int(int)> flexible = fast;
std::cout << fast(1) << ' ' << flexible(1) << '\n';
return 0;
}Valintaopas
Lyhyt opas:
- Tarvitsetteko tallentaa minkä tahansa kutsuttavan olion?
std::function. - Vastaanotatteko vain yhden kutsuttavan olion yleiskäyttöisessä funktiossa? Malliparametri.
- Tarvitsetteko suoraan käyttöpaikassa määritettyä, tilaa sisältävää toiminnallisuutta? Lambda.
- C-rajapinta tai tilaton toiminnallisuus? Funktio-osoitin.
#include <iostream>
#include <functional>
void runStored(const std::function<void()>& cb) { cb(); }
template <typename F>
void runGeneric(F f) { f(); }
int main() {
runStored([] { std::cout << "stored\n"; });
runGeneric([] { std::cout << "generic\n"; });
return 0;
}Kaiken yhdistäminen
Pieni tapahtumajärjestelmä voi vastaanottaa käsittelijöitä yleiskäyttöisesti mutta tallentaa ne std::function-muuttujaan, jotta ne voidaan kutsua myöhemmin.
#include <iostream>
#include <functional>
#include <vector>
struct Dispatcher {
std::vector<std::function<void(int)>> handlers;
template <typename F> void on(F f) { handlers.emplace_back(f); }
void fire(int e) { for (auto& h : handlers) h(e); }
};
int main() {
Dispatcher d;
d.on([](int e) { std::cout << "got " << e << '\n'; });
d.fire(7);
return 0;
}Pikatarkistus
Testatkaa, miten hyvin ymmärrätte kutsuttavien olioiden valintaa.
Kertaus
Opitte valitsemaan kutsuttavan olion:
- funktio-osoitin tilattomille ja C-yhteensopiville takaisinkutsuille
- lambda oletusvalintana suoraan määritettävälle, tilaa sisältävälle toiminnallisuudelle
- funktori uudelleenkäytettäville nimetyille operaatioille
- malliparametri, kun vain vastaanotatte kutsuttavan olion (nopein vaihtoehto)
std::function, kun teidän on tallennettava kutsuttava olio, jonka tyyppiä ei tunneta
Tämä päättää funktio-olioita ja std::bind-toimintoa käsittelevän kurssin.
Opi C++ tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 51
- Oppitunnit
- 203
Usein kysytyt kysymykset
Onko oppitunti ”Kutsuttavien olioiden valinta” ilmainen?
Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa C++ Academy-oppimispolun 3 oppituntia, myös oppitunnin “Kutsuttavien olioiden valinta”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. C++ Academy-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”Kutsuttavien olioiden valinta”?
Lambdat, bind vai osoittimet Harjoittelet C++ Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni C++ Academy-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin C++ Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 4/4.
Kuinka kauan ”Kutsuttavien olioiden valinta”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä C++ Academy-oppitunnilla?
Kyllä. Jokainen C++ Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- Funktio-osoittimet
- std::function
- std::bind
- Kutsuttavien olioiden valinta