gestion mémoire

Je n'arrive pas à  comprendre la différence entre les deux lignes ci-dessous:
1) return [[[NSString alloc] initWithString:machin] autoRelease] ;

2) return [NSString stringWithString:machin] ;
J'ai l'impression que les résultats sont identiques puisque dans les deux cas, le string est dans l'autoRelease Pool et disparaitra à  la fin de la boucle d'évènement. Mais probablement que je me plante et si c'est le cas pourquoi écrire l'un plus tôt que l'autre?

A vot' bon coe“ur msieur dames.

Réponses

  • MalaMala Membre, Modérateur
    La deuxième ligne fait appel à  un constructeur de commodité de la classe. Elle fait exactement la même chose mais c'est syntaxiquement plus court. D'où l'appellation "commodité".
  • C'est bien ce qu'il me semblait!
  • AliGatorAliGator Membre, Modérateur
    Oui toutes les méthodes commençant par le nom de la classe sont par convention des constructeurs de commodité qui ne font que alloc+init+autorelease. [NSString stringWithFormat:@un nombre : %d,5] est donc exactement équivalent à  [[[NSString alloc] initWithFormat:@un nombre : %d,5] autorelease] par exemple. [NSArray array] est exactement équivalent à  [[[NSArray alloc] init] autorelease]. etc.



    NB : à  savoir que NSString est un cas un peu particulier car fortement optimisé (et en plus c'est un "class cluster"), ce qui fait que ce n'est pas toujours le meilleur exemple à  prendre pour essayer de comprendre les mécanismes internes. Par exemple [NSString stringWithString:@toto] est exactement aussi équivalent à  @toto directement (et ça n'a donc aucun intérêt d'utiliser stringWithString), puisque les chaà®nes constantes sont compilées dans la partie des constantes du binaire, puisque pour les NSString on peut directement mettre des litéraux. (stringWithString n'a éventuellement de sens que pour être utilisé par les sous-classes, mais l'appeler sur la classe NSString ne sert à  rien).
  • Bonjour,



    Merci pour c'est info!! C'est bon à  savoir image/wink.png' class='bbc_emoticon' alt=';)' />
  • tabliertablier Membre
    mars 2012 modifié #6
    Si j'utilise 55 fois @toto est-ce que le compilateur va le voir et ne le compiler qu'une fois?

    Ce qui me donne parfois des soucis est de savoir quand un objet de l'autoRelease Pool va être libéré! Je trouve que ce n'est pas toujours évident. Si j'ai bien compris, l'objet est libéré en fin de boucle d'évènement si son "retain count" est à  zéro. Vrai/Faux ?
  • L'autorelease permet simplement de dire que le release sera fait plus tard. Le plus tard, c'est quand l'autoreleasePool (auquel est associé le release) est détruit de la mémoire. Dans le thread principal de l'application, un autoreleasePool est créé automatiquement à  chaque événement, mais dans les threads secondaires, c'est autre chose. En cas d'utilisation de NSThread ou NSOperation, il faut créer son propre autoreleasePool. Par contre, le mécanisme est automatique en cas d'utilisation de GCD.
  • AliGatorAliGator Membre, Modérateur
    'tablier' a écrit:
    Si j'utilise 55 fois @toto est-ce que le compilateur va le voir et ne le compiler qu'une fois?
    Oui, bien sûr.


    'tablier' a écrit:
    Ce qui me donne parfois des soucis est de savoir quand un objet de l'autoRelease Pool va être libéré! Je trouve que ce n'est pas toujours évident. Si j'ai bien compris, l'objet est libéré en fin de boucle d'évènement si son "retain count" est à  zéro. Vrai/Faux ?
    C'est pas compliqué dans l'absolu, mais ce qui rend sans doute ça obscur c'est que tu ne crées pas explicitement la première NSAutoreleasePool de haut niveau, associée à  la RunLoop principale de ton programme, et que tu ne sais pas forcément ce qu'est une RunLoop



    En fait, partons sur un exemple de code, où on crée nous-même explicitement une NSAutoreleasePool :
    NSAutoreleasePool* arp = [[NSAutoreleasePool alloc] init];<br />
    <br />
    // On crée 3 objets qui sont autorelease<br />
    NSArray* array = [NSArray array];<br />
    NSNumber* num = [NSNumber numberWithInt:5];<br />
    <br />
    NSDictionary* dict = [[[NSDictionary alloc] init] autorelease]; // ou [NSDictionary dictionary] c&#39;est juste pour montrer une variante<br />
    <br />
    <br />
    [arp release];
    
    Ici les 3 objets qu'on a créés, entre la création de notre NSAutoreleasePool en première ligne et sa destruction en dernière ligne, ne vont pas être libérés dès la réception du message "autorelease" (comme ça serait le cas si on leur avait envoyé "release" au lieu d'autorelease). Au lieu de ça, ces objets vont être mis dans la dernière NSAutoreleasePool qu'on a créée, donc dans notre cas celle qu'on a appelé "arp". Et c'est seulement quand l'AutoreleasePool arp va être détruite qu'elle va en profiter pour envoyer le vrai message "release" à  tous les objets qu'elle avait enregistrés (à  tous les objets qui avaient reçus un message autorelease précédemment).



    Donc pour répondre à  la question "quand est-ce qu'un objet autorelease est effectivement releasé" bah c'est quand l'autoreleasepool est détruite. Ou quand elle est vidée (drain).



    Maintenant il se trouve que si tu regardes dans ton main.m, Xcode en créant ton projet t'a aussi créé une NSAutoreleasePool dans le main avant d'appeler UIApplicationMain(). Donc si tu ne crées pas de NSAutoreleasePool explicitement comme on a fait dans l'exemple ci-dessous, les objets qui recoivent "autorelease" vont se mettre dans cette NSAutoreleasePool. Et ils seront vidés à  chaque itération de la RunLoop.
  • tabliertablier Membre
    mars 2012 modifié #9
    Il faut que je re-lise un peu de doc. Pour moi la RunLoop c'est une boucle de distribution des évènements. Un peu comme sous Mac OS 6, 7, 8 , 9 ou il fallait traiter soi-même les évènements qui vous étaient destinés et repasser les autres évènements au processus suivant inscrit sur la boucle et actif (C'est entendu, j'ai simplifié). J'ai l'impression que la RunLoop fait la même chose sans qu'on ne la voit jamais (sauf si on veut traiter directement les évènements).

    Bon je vais relire un peu de doc.
  • zoczoc Membre
    Bah oui, la RunLoop, c'est toujours ça, sauf que Cocoa en propose une implémentation par défaut, donc plus besoin de la coder soi-même, et qu'il n'est de toute façon plus nécessaire de passer les autres évènements au processus suivant, puisque MacOS X fonctionne en multitache préemptif, là  ou MacOS ne proposait qu'un multitache coopératif.
Connectez-vous ou Inscrivez-vous pour répondre.