146 votes

Qu'est-ce que la boxe et le déballage et quels sont les compromis?

Je cherche une réponse claire, concise et précise.

Idéalement comme la réponse réelle, bien que les liens vers de bonnes explications soient les bienvenus.

207voto

Peter Burns Points 17420

Coffret valeurs sont des structures de données qui sont minimes wrappers autour de types primitifs*. Coffret valeurs sont généralement enregistrées comme des pointeurs vers des objets sur le tas.

Ainsi, boîte à des valeurs d'utiliser plus de mémoire et de prendre au minimum deux la mémoire de recherches pour l'accès: une fois pour obtenir le pointeur, et un autre pour suivre le pointeur de la primitive. Évidemment, ce n'est pas le genre de chose que vous voulez dans votre intérieur des boucles. Sur l'autre main, boîte à des valeurs généralement mieux jouer avec d'autres types dans le système. Depuis qu'ils sont de première classe de structures de données dans la langue, ils ont attendus des métadonnées et de la structure que d'autres structures de données ont.

En Java, et Haskell générique collections ne peuvent pas contenir d'unboxed valeurs. Générique collections .NET peut contenir unboxed valeurs, sans pénalités. Où Java est les génériques ne sont utilisés que pour la compilation vérification de type .NET va générer des classes spécifiques pour chaque type générique instanciée au moment de l'exécution.

Java et Haskell ont unboxed tableaux, mais ils sont nettement moins pratique que les autres collections. Toutefois, lorsque le pic de performance est nécessaire, il vaut la peine un peu de désagréments à éviter la surcharge de boxing et unboxing.

* Pour cette discussion, une valeur primitive est tout qui peut être stocké sur la pile d'appel, plutôt que d'être stockés comme un pointeur vers une valeur sur le tas. Souvent c'est juste le type de machine (ints, des flotteurs, etc), les structures, et parfois statique de la taille des tableaux. .NET-la terre appelle des types de valeur (par opposition à des types de référence). Java gens les appellent les types primitifs. Haskellions juste de les appeler "unboxed".

** Je suis également l'accent sur Java, Haskell, et C# dans cette réponse, parce que c'est ce que je sais. Pour ce que ça vaut, Python, Ruby, Javascript et tous ont exclusivement en boîte valeurs. Ceci est également connu comme le "Tout est objet" approche***.

*** Mise en garde: suffisamment avancée compilateur / JIT peut, dans certains cas, de détecter qu'une valeur qui est sémantiquement en boîte quand on regarde la source, peuvent en toute sécurité être un décaissement de la valeur au moment de l'exécution. En essence, grâce à l'utilisation brillante de la langue des réalisateurs vos boîtes sont parfois gratuits.

130voto

Christian Hagelid Points 4795

à partir de la version 3.0 # en bref :

La boxe est l'acte consistant à transformer un type de valeur en un type de référence:

 int x = 9; 
object o = x; // boxing the int
 

le déballage est ... l'inverse:

 // unboxing o
object o = 9; 
int x = (int)o; 
 

74voto

Justin Standard Points 15312

Boxing et unboxing est le processus de conversion d'une valeur primitive dans un orientée objet classe wrapper (boxe), ou de convertir une valeur d'un orientée objet classe wrapper retour à la valeur primitive (unboxing).

Par exemple, en java, vous pouvez avoir besoin de convertir un int valeur en Integer (boxe) si vous souhaitez le stocker dans un Collection parce que les primitives ne peuvent pas être stockées dans un Collection, seuls les objets. Mais quand vous voulez sortir de l' Collection vous pouvez obtenir la valeur en int et pas un Integer de sorte que vous vous unbox.

Boxing et unboxing n'est pas foncièrement mauvais, mais c'est un compromis. En fonction de la langue mise en œuvre, il peut être plus lent et plus gourmande en mémoire que juste à l'aide de primitives. Cependant, elle peut également vous permettre d'utiliser plus de données au niveau des structures et de parvenir à une plus grande flexibilité dans votre code.

Ces jours, il est le plus souvent abordée dans le contexte de Java (et d'autres langues) "l'autoboxing/autounboxing". Voici une java centrée sur l'explication de l'autoboxing.

23voto

Keith Points 46288

Dans .Net:

Souvent, vous ne pouvez pas compter sur ce que le type de variable à une fonction de la consommation, de sorte que vous besoin d'utiliser une variable objet qui s'étend à partir du plus petit dénominateur commun .Net, c'est - object.

Toutefois object est une classe et stocke son contenu comme une référence.

List<int> notBoxed = new List<int> { 1, 2, 3 };
int i = notBoxed[1]; // this is the actual value

List<object> boxed = new List<object> { 1, 2, 3 };
int j = (int) boxed[1]; // this is an object that can be 'unboxed' to an int

Bien que ces deux contiennent la même information de la deuxième liste est plus gros et plus lent. Chaque valeur dans la deuxième liste est en fait une référence à un object que détient l' int.

Ceci est appelé la boîte parce que l' int est enveloppé par l' object. Lors de ses acteurs l' int est unboxed - reconverties à la valeur.

Pour les types de valeur (c'est à dire tous structs) c'est lent, et potentiellement utilise beaucoup plus d'espace.

Pour les types de référence (c'est à dire tous classes) ce qui est beaucoup moins un problème, car ils sont stockés en tant que référence, de toute façon.

Un autre problème avec une boîte de type de valeur, c'est qu'il n'est pas évident que vous avez à traiter avec la boîte, plutôt que de la valeur. Lorsque vous comparez les deux structs alors vous êtes comparaison de valeurs, mais lorsque vous comparez les deux classes ensuite (par défaut), vous allez comparer la référence - c'est à dire sont-ils les mêmes?

Cela peut être déroutant lorsque vous traitez avec boîte de types de valeur:

int a = 7;
int b = 7;

if(a == b) // Evaluates to true, because a and b have the same value

object c = (object) 7;
object d = (object) 7;

if(c == d) // Evaluates to false, because c and d are different instances

Il est facile à contourner:

if(c.Equals(d)) // Evaluates to true because it calls the underlying int's equals

if(((int) c) == ((int) d)) // Evaluates to true once the values are cast

Cependant, il est une autre chose d'être prudent lorsque vous traitez avec boîte valeurs.

2voto

Jonathan Webb Points 1228

Les collections génériques .NET FCL:

 List<T>
Dictionary<TKey, UValue>
SortedDictionary<TKey, UValue>
Stack<T>
Queue<T>
LinkedList<T>
 

ont tous été conçus pour surmonter les problèmes de performances de la boxe et de la déballage dans les implémentations précédentes de la collection.

Pour plus d'informations, voir le chapitre 16, CLR via C # (2e édition) .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X