Namespaces
Variants

std::accumulate

Von de.cppreference.net
 
 
Algorithmen-Bibliothek
Eingeschränkte Algorithmen und Algorithmen auf Bereichen (C++20)
Eingeschränkte Algorithmen, z.B. ranges::copy, ranges::sort, ...
Nicht modifizierende Sequenzoperationen    
Batch-Operationen
(C++17)
Suchoperationen
Modifizierende Sequenzoperationen
Kopieroperationen
(C++11)
(C++11)
Tauschoperationen
Transformationsoperationen
Generierungsoperationen
Entfernungsoperationen
Reihenfolgeändernde Operationen
(bis C++17)(C++11)
(C++20)(C++20)
Stichprobenoperationen
(C++17)

Sortier- und verwandte Operationen
Partitionierungsoperationen
(C++11)    

Sortieroperationen
Binäre Suchoperationen
(auf partitionierten Bereichen)
Mengenoperationen (auf sortierten Bereichen)
Mischoperationen (auf sortierten Bereichen)
Heap-Operationen
Minimum/Maximum-Operationen
(C++11)
(C++17)
Lexikografische Vergleichsoperationen
Permutationsoperationen


 
 
Definiert in Header <numeric>
template< class InputIt, class T >
T accumulate( InputIt first, InputIt last, T init );
(1) (constexpr seit C++20)
template< class InputIt, class T, class BinaryOp >
T accumulate( InputIt first, InputIt last, T init, BinaryOp op );
(2) (constexpr seit C++20)

Berechnet die Summe des gegebenen Wertes init und der Elemente im Bereich [first, last).

1) Initialisiert den Akkumulator acc (vom Typ T) mit dem Anfangswert init und modifiziert ihn dann mit acc = acc + *i(bis C++20)acc = std::move(acc) + *i(seit C++20) für jeden Iterator i im Bereich [first, last) in der Reihenfolge.
2) Initialisiert den Akkumulator acc (vom Typ T) mit dem Anfangswert init und modifiziert ihn dann mit acc = op(acc, *i)(bis C++20)acc = op(std::move(acc), *i)(seit C++20) für jeden Iterator i im Bereich [first, last) in der Reihenfolge.

Wenn eine der folgenden Bedingungen erfüllt ist, ist das Verhalten undefiniert:

  • T ist nicht CopyConstructible.
  • T ist nicht CopyAssignable.
  • op modifiziert ein beliebiges Element von [first, last).
  • op macht einen Iterator oder Teilbereich in [first, last] ungültig.

Parameter

first, last - das Paar von Iteratoren, das den Bereich der zu akkumulierenden Elemente definiert
init - Anfangswert der Akkumulation
op - binäres Operationsfunktionsobjekt, das angewendet wird.

Die Signatur der Funktion sollte der folgenden entsprechen:

Ret fun(const Type1 &a, const Type2 &b);

Die Signatur muss kein const & enthalten.
Der Typ Type1 muss so sein, dass ein Objekt vom Typ T implizit in Type1 konvertiert werden kann. Der Typ Type2 muss so sein, dass ein Objekt vom Typ InputIt dereferenziert und dann implizit in Type2 konvertiert werden kann. Der Typ Ret muss so sein, dass einem Objekt vom Typ T ein Wert vom Typ Ret zugewiesen werden kann. ​

Typanforderungen
-
InputIt muss die Anforderungen von LegacyInputIterator erfüllen.

Rückgabewert

acc nach allen Modifikationen.

Mögliche Implementierung

accumulate (1)
template<class InputIt, class T>
constexpr // since C++20
T accumulate(InputIt first, InputIt last, T init)
{
    for (; first != last; ++first)
        init = std::move(init) + *first; // std::move since C++20
    
    return init;
}
accumulate (2)
template<class InputIt, class T, class BinaryOperation>
constexpr // since C++20
T accumulate(InputIt first, InputIt last, T init, BinaryOperation op)
{
    for (; first != last; ++first)
        init = op(std::move(init), *first); // std::move since C++20
    
    return init;
}

Anmerkungen

std::accumulate führt eine linke Faltung durch. Um eine rechte Faltung durchzuführen, muss man die Reihenfolge der Argumente des binären Operators umkehren und reverse Iteratoren verwenden.

Wenn man es der Typinferenz überlässt, arbeitet op mit Werten des gleichen Typs wie init, was zu einer unerwünschten Umwandlung der Iteratorelemente führen kann. Zum Beispiel liefert std::accumulate(v.begin(), v.end(), 0) wahrscheinlich nicht das gewünschte Ergebnis, wenn v vom Typ std::vector<double> ist.

Beispiel

#include <functional>
#include <iostream>
#include <numeric>
#include <string>
#include <vector>
 
int main()
{
    std::vector<int> v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    
    int sum = std::accumulate(v.begin(), v.end(), 0);
    int product = std::accumulate(v.begin(), v.end(), 1, std::multiplies<int>());
    
    auto dash_fold = [](std::string a, int b)
    {
        return std::move(a) + '-' + std::to_string(b);
    };
    
    std::string s = std::accumulate(std::next(v.begin()), v.end(),
                                    std::to_string(v[0]), // start with first element
                                    dash_fold);
    
    // Right fold using reverse iterators
    std::string rs = std::accumulate(std::next(v.rbegin()), v.rend(),
                                     std::to_string(v.back()), // start with last element
                                     dash_fold);
    
    std::cout << "sum: " << sum << '\n'
              << "product: " << product << '\n'
              << "dash-separated string: " << s << '\n'
              << "dash-separated string (right-folded): " << rs << '\n';
}

Ausgabe:

sum: 55
product: 3628800
dash-separated string: 1-2-3-4-5-6-7-8-9-10
dash-separated string (right-folded): 10-9-8-7-6-5-4-3-2-1

Fehlerberichte

Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR Angewandt auf Verhalten wie veröffentlicht Korrektes Verhalten
LWG 242 C++98 op konnte keine Nebenwirkungen haben es darf die beteiligten Bereiche nicht modifizieren

Siehe auch

berechnet die Differenzen zwischen benachbarten Elementen in einem Bereich
(Funktionsschablone)
berechnet das innere Produkt zweier Elementbereiche
(Funktionsschablone)
berechnet die partielle Summe eines Elementbereichs
(Funktionsschablone)
(C++17)
ähnlich wie std::accumulate, jedoch ohne feste Reihenfolge
(Funktionsschablone)
faltet einen Elementbereich links
(Algorithmusfunktionsobjekt)