Les pointeurs sont utiles pour plusieurs raisons. Les pointeurs permettent de contrôler disposition de la mémoire (affecte l'efficacité de cache du PROCESSEUR). Allez on peut définir une structure où tous les membres sont dans la mémoire contiguë:
type Point struct {
x, y int
}
type LineSegment struct {
source, destination Point
}
Dans ce cas, l' Point
des structures sont intégrés au sein de l' LineSegment
struct. Mais vous ne pouvez pas toujours intégrer directement les données. Si vous voulez soutenir des structures telles que les arbres binaires ou liste liée, alors vous avez besoin à l'appui de une sorte de pointeur.
type TreeNode {
value int
left *TreeNode
right *TreeNode
}
Java, Python, etc n'ont pas ce problème car il ne vous permet pas d'intégrer des types de composé, donc il n'est pas nécessaire d'un point de vue syntaxique de différencier entre l'incorporation et de pointage.
Problèmes avec C# structs résolu avec les pointeurs
Une alternative possible pour accomplir la même chose est à différencier struct
et class
comme C#. Mais ce n'est pas sans problèmes non plus. Parce qu'il vous oblige à toujours faire de la valeur sémantique, même lorsque cela n'a pas de sens.
E. g. dire que j'ai une ligne de tableau de 4x4 matricies utilisés pour représenter les nœuds dans un graphe de scène ou quelque chose de similaires. J'ai pu pour qu'en C#, mais je ne pouvais pas passer entre accèdent en tant que valeur ou un pointeur. Si c'était un tableau de points je ne voudrais pas utiliser un pointeur. E. g:
// In this case we want to copy points on computation
var points [1024]Point
var q Point = calcSomePoint()
for p in range points {
result := dotProduct(p, q)
doStuff(result)
}
// We don't want to copy matricies each time we perform a computation because
// they are big, but we want them in contiguous memory
var matricies [1024]Matrix4x4
var n Matrix4x4 = caclSomeMatrix()
for m in range matricies {
multiply(&n, &m) // Avoid copying 2*4*4*8 = 256 bytes on each computation
}
Donc, en C# vous êtes toujours obligé d'envoyer struct autour de en les copiant. Cela peut facilement tuer la performance dans une application C# qui est pourquoi MS recommande structs pas de plus de 16 octets. Avec Go, puisqu'il prend en charge les pointeurs vous pouvez choisir exactement où vous voulez passer vos structures autour de l'utilisation des pointeurs et quand vous voulez les copier. Cela rend plus facile pour Aller au travail avec de grandes structures sans tuer la performance.
Personnalisé Allocateur De Mémoire
En utilisant les pointeurs vous pouvez également créer votre propre piscine allocateur (ce qui est très simplifié avec un grand nombre de vérifications retiré juste vous montrer le principe):
type TreeNode {
value int
left *TreeNode
right *TreeNode
nextFreeNode *TreeNode; // For memory allocation
}
var pool [1024]TreeNode
var firstFreeNode *TreeNode = &pool[0]
func poolAlloc() *TreeNode {
node := firstFreeNode
firstFreeNode = firstFreeNode.nextFreeNode
return node
}
func freeNode(node *TreeNode) {
node.nextFreeNode = firstFreeNode
firstFreeNode = node
}
Échanger deux valeurs
Les pointeurs permet également de mettre en oeuvre swap
. C'est de permuter les valeurs de deux variables:
func swap(a *int, b *int) {
temp := *a
*a = *b
*b = temp
}
Conclusion
Java n'a jamais été pleinement en mesure de remplacer C++ pour la programmation de systèmes à des endroits tels que Google, en partie parce que la performance ne peut pas être réglée à la même étendre en raison du manque de capacité de contrôler disposition de la mémoire et de l'usage (le cache affecter les performances de manière significative). Aller a cherché à remplacer C++ dans de nombreux domaines et a donc besoin de l'appui des pointeurs.