web-dev-qa-db-fra.com

Comment mettre à zéro rapidement un tableau?

Je le fais actuellement dans une boucle for, et je sais qu'en C il y a l'API ZeroMemory, mais cela ne semble pas être disponible en C #. Le Array.fill quelque peu équivalent de Java n'existe pas non plus. Je me demande simplement s'il existe un moyen plus facile/plus rapide?

54
esac

Essayez Array.Clear () :

Définit une plage d'éléments dans le tableau à zéro, à false ou à null (rien dans Visual Basic), selon le type d'élément.

103
Jason Punyon
  • C++: memset(array, 0, array_length_in_bytes);

  • C++ 11: array.fill(0);

  • C #: Array.Clear(array, startingIndex, length);

  • Java: Arrays.fill(array, value);

48
Chap
Array.Clear(integerArray, 0, integerArray.Length);
16
Dustin Getz

[~ # ~] mise à jour [~ # ~]

Sur la base des benchmark concernant les performances de Array.Clear() et array[x] = default(T), nous pouvons affirmer qu'il existe deux cas majeurs à considérer lors de la mise à zéro d'un tableau:

A) Il existe un tableau de 1 à 76 éléments ;

B) Il existe un tableau de 77 éléments ou plus .

Ainsi, la ligne orange sur le graphique représente l'approche Array.Clear().

La ligne bleue sur le graphique représente l'approche array[x] = default(T) (itération sur le tableau et définition de ses valeurs sur default(T)).

enter image description here

Vous pouvez écrire une fois un assistant pour faire ce travail, comme ceci:

public static class ArrayHelper
{
    // Performance-oriented algorithm selection
    public static void SelfSetToDefaults<T>(this T[] sourceArray)
    {
        if (sourceArray.Length <= 76)
        {
            for (int i = 0; i < sourceArray.Length; i++)
            {
                sourceArray[i] = default(T);
            }
        }
        else { // 77+
             Array.Clear(
                 array: sourceArray,
                 index: 0,
                 length: sourceArray.Length);
        }
    }
}

Usage:

someArray.SelfSetToDefaults();
14
AndreyWD

Plusieurs personnes ont posté des réponses, puis les ont supprimées, disant que dans n'importe quelle langue, une boucle for sera aussi performante qu'un memset ou FillMemory ou autre.

Par exemple, un compilateur peut le découper en morceaux alignés 64 bits pour tirer parti d'une instruction d'affectation zéro 64 bits, si disponible. Il faudra tenir compte de l'alignement et des choses. L'implémentation de Memset n'est certainement pas anodine.

un memset.asm . Voir aussi memset-is-plus rapide que-simple-loop.html .

Ne sous-estimez jamais l'infinie déviance des compilateurs et des écrivains de bibliothèque standard.

12
Dustin Getz

Appel de la méthode à l'aide de l'importation de DLL, rapide et facile à utiliser :)

 [DllImport("msvcrt.dll", EntryPoint = "memset", CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
 public static extern IntPtr MemSet(IntPtr dest, int c, int byteCount);

c est la valeur que vous souhaitez définir dans la mémoire

OR

[DllImport("kernel32.dll", EntryPoint="RtlZeroMemory")]
public unsafe static extern bool ZeroMemory(byte* destination, int length);

cela ne met le tableau donné à zéro

2
Reaven Clan