it-swarm.com.de

Die schnellste Möglichkeit, jeden Wert von std :: vector <int> auf zurückzusetzen

Wie kann ich am schnellsten jeden Wert eines std::vector<int> auf 0 zurücksetzen und die Anfangsgröße der Vektoren beibehalten? 

Eine for-Schleife mit dem Operator []? 

145
std::fill(v.begin(), v.end(), 0);
264
Cat Plus Plus

Wie immer, wenn Sie am schnellsten fragen: Messen! Verwenden der obigen Methoden (auf einem Mac mit Clang):

Method      |  executable size  |  Time Taken (in sec) |
            |  -O0    |  -O3    |  -O0      |  -O3     |  
------------|---------|---------|-----------|----------|
1. memset   | 17 kB   | 8.6 kB  | 0.125     | 0.124    |
2. fill     | 19 kB   | 8.6 kB  | 13.4      | 0.124    |
3. manual   | 19 kB   | 8.6 kB  | 14.5      | 0.124    |
4. assign   | 24 kB   | 9.0 kB  | 1.9       | 0.591    |

unter Verwendung von 100000 Iterationen an einem Vektor von 10000 Ints.

Editieren: Wenn sich diese Zahlen plausibel ändern, kann dies dazu führen, dass einige Vertrauen besteht (nicht so gut wie das Überprüfen des endgültigen Assembly-Codes), dass der künstliche Benchmark nicht vollständig optimiert wurde. Natürlich ist es am besten, die Leistung unter realen Bedingungen zu messen Ende Bearbeiten  

als Referenz für den verwendeten Code: 

#include <vector>

#define TEST_METHOD 1
const size_t TEST_ITERATIONS = 100000;
const size_t TEST_ARRAY_SIZE = 10000;

int main(int argc, char** argv) {

   std::vector<int> v(TEST_ARRAY_SIZE, 0);

   for(size_t i = 0; i < TEST_ITERATIONS; ++i) {
   #if TEST_METHOD == 1 
      memset(&v[0], 0, v.size() * sizeof v[0]);
   #Elif TEST_METHOD == 2
      std::fill(v.begin(), v.end(), 0);
   #Elif TEST_METHOD == 3
      for (std::vector<int>::iterator it=v.begin(), end=v.end(); it!=end; ++it) {
         *it = 0;
      }
   #Elif TEST_METHOD == 4
      v.assign(v.size(),0);
   #endif
   }

   return EXIT_SUCCESS;
}

Fazit: use std::fill (weil, wie andere gesagt haben, es am idiomatischsten ist)!

121
Fabio Fracassi

Wie wäre es mit der Memberfunktion assign?

some_vector.assign(some_vector.size(), 0);
21
fredoverflow

Wenn es nur ein Vektor von ganzen Zahlen ist, würde ich zuerst versuchen:

memset(&my_vector[0], 0, my_vector.size() * sizeof my_vector[0]);

Es ist nicht sehr C++, daher bin ich sicher, dass jemand den richtigen Weg dafür bietet. :)

12
unwind

versuchen 

std::fill

und auch

std::size siz = vec.size();
//no memory allocating
vec.resize(0);
vec.resize(siz, 0);
2
nttstar

Ich hatte die gleiche Frage, aber über ziemlich kurz vector<bool> (afaik der Standard erlaubt, sie intern anders als nur ein fortlaufendes Array von booleschen Elementen zu implementieren). Daher wiederholte ich die leicht modifizierten Tests von Fabio Fracassi. Die Ergebnisse lauten wie folgt (Zeiten in Sekunden):

            -O0       -O3
         --------  --------
memset     0.666     1.045
fill      19.357     1.066
iterator  67.368     1.043
assign    17.975     0.530
for i     22.610     1.004

Anscheinend ist vector<bool>::assign() für diese Größen anscheinend schneller. Der für Tests verwendete Code:

#include <vector>
#include <cstring>
#include <cstdlib>

#define TEST_METHOD 5
const size_t TEST_ITERATIONS = 34359738;
const size_t TEST_ARRAY_SIZE = 200;

using namespace std;

int main(int argc, char** argv) {

    std::vector<int> v(TEST_ARRAY_SIZE, 0);

    for(size_t i = 0; i < TEST_ITERATIONS; ++i) {
#if TEST_METHOD == 1
        memset(&v[0], false, v.size() * sizeof v[0]);
#Elif TEST_METHOD == 2
        std::fill(v.begin(), v.end(), false);
   #Elif TEST_METHOD == 3
        for (std::vector<int>::iterator it=v.begin(), end=v.end(); it!=end; ++it) {
            *it = 0;
        }
   #Elif TEST_METHOD == 4
      v.assign(v.size(),false);
   #Elif TEST_METHOD == 5
      for (size_t i = 0; i < TEST_ARRAY_SIZE; i++) {
          v[i] = false;
      }
#endif
    }

    return EXIT_SUCCESS;
}

Ich habe GCC 7.2.0 Compiler unter Ubuntu 17.10 verwendet. Die Befehlszeile zum Kompilieren:

g++ -std=c++11 -O0 main.cpp
g++ -std=c++11 -O3 main.cpp
0