#include <iostream>
#include <string>
int addiere(int a, int b) { return a + b; }
double potenz(double basis, int exponent = 2) { // Standardwert
double r = 1;
for (int i = 0; i < exponent; i++) r *= basis;
return r;
}
// Überladen: gleicher Name, andere Parameter
std::string beschreibe(int x) { return "int " + std::to_string(x); }
std::string beschreibe(double x) { return "double " + std::to_string(x).substr(0, 4); }
std::string beschreibe(const std::string& x) { return "string " + x; }
// Mehrere Rückgabewerte über struct oder Tupel
struct Ergebnis { int quotient, rest; };
Ergebnis teile(int a, int b) { return {a / b, a % b}; }
int main() {
std::cout << addiere(3, 4) << ' ' << potenz(3) << ' ' << potenz(2, 10) << '\n';
std::cout << beschreibe(5) << ", " << beschreibe(2.5) << ", " << beschreibe(std::string("hi")) << '\n';
auto [q, r] = teile(17, 5);
std::cout << q << " Rest " << r << '\n';
return 0;
}7 9 1024 int 5, double 2.50, string hi 3 Rest 2
Parameterübergabe
| Fall | Schreibweise |
|---|---|
| kleiner Wert, nur lesen | int x, double d |
| großes Objekt, nur lesen | const std::string& s |
| Objekt ändern (Ausgabeparameter) | std::vector<int>& v |
| Objekt übernehmen und behalten | std::string s + std::move (siehe Move-Semantik) |
| optionaler Parameter | std::optional<T> oder Standardwert |
Lambdas
Ein Lambda ist eine namenlose Funktion, die direkt an der Stelle geschrieben wird, wo man sie braucht:
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
int main() {
auto quadrat = [](int x) { return x * x; };
std::cout << quadrat(7) << '\n';
std::vector<int> z{5, 3, 9, 1, 7};
std::sort(z.begin(), z.end(), [](int a, int b) { return a > b; }); // absteigend
for (int x : z) std::cout << x << ' ';
std::cout << '\n';
int schwelle = 4;
auto groesser = [schwelle](int x) { return x > schwelle; }; // [schwelle]: Kopie "eingefangen"
std::cout << std::count_if(z.begin(), z.end(), groesser) << '\n';
int zaehler = 0;
auto zaehle = [&zaehler]() { return ++zaehler; }; // [&zaehler]: Referenz
zaehle(); zaehle();
std::cout << zaehler << '\n';
std::function<int(int)> fib = [&fib](int n) { return n < 2 ? n : fib(n - 1) + fib(n - 2); };
std::cout << fib(15) << '\n';
auto allgemein = [](auto a, auto b) { return a + b; }; // generisches Lambda
std::cout << allgemein(1, 2) << ' ' << allgemein(1.5, 2.5) << '\n';
return 0;
}49 9 7 5 3 1 3 2 610 3 4
In den eckigen Klammern steht, was das Lambda von außen einfängt: [] nichts, [x] Kopie, [&x] Referenz, [=] alles als Kopie, [&] alles als Referenz.
constexpr: Berechnung zur Übersetzungszeit
#include <iostream>
#include <array>
constexpr int fakultaet(int n) { return n <= 1 ? 1 : n * fakultaet(n - 1); }
int main() {
constexpr int f5 = fakultaet(5); // wird vom Compiler berechnet
std::array<int, fakultaet(4)> feld{}; // Größe zur Übersetzungszeit bekannt
static_assert(fakultaet(3) == 6, "Rechenfehler");
std::cout << f5 << ' ' << feld.size() << '\n';
return 0;
}120 24
constexpr verlagert Arbeit vom Programmlauf zum Übersetzen. static_assert prüft Bedingungen schon beim Kompilieren.
Funktionen höherer Ordnung
#include <iostream>
#include <functional>
#include <vector>
#include <string>
std::function<int(int)> malGlied(int faktor) {
return [faktor](int x) { return x * faktor; };
}
template <typename F>
void fuerJeden(const std::vector<std::string>& l, F f) { for (const auto& s : l) f(s); }
int main() {
auto dreifach = malGlied(3);
std::cout << dreifach(14) << '\n';
fuerJeden({"a", "b"}, [](const std::string& s) { std::cout << "[" << s << "]"; });
std::cout << '\n';
return 0;
}42 [a][b]
noexcept, [[nodiscard]] und Attribute
noexcept: Die Funktion wirft keine Ausnahme (hilft dem Compiler beim Optimieren)[[nodiscard]]: Der Rückgabewert darf nicht ignoriert werden (wichtig bei Fehlercodes)[[maybe_unused]],[[deprecated("Text")]],[[fallthrough]]
Merke
- Standardwerte und Überladen erleichtern Aufrufe; große Parameter als
const& - Mehrere Ergebnisse:
structoderstd::tuplemit Structured Bindings - Lambdas:
[Capture](Parameter) { Rumpf };[=]kopiert,[&]verweist constexprrechnet zur Übersetzungszeit,static_assertprüft dortstd::functionspeichert beliebige aufrufbare Objekte
Aufgabe
Sortiere einen Vektor von Strings nach Länge und alphabetisch mit einem Lambda.