Il y a d'excellentes réponses là-bas, donc j'ai juste ajouter un peu de choses oubliées.
0. RAII est sur les étendues
RAII est sujet à la fois:
- l'acquisition d'une ressource (n'importe quelle ressource) dans le constructeur, et de l'onu-l'acquisition dans le destructeur.
- ayant le constructeur exécutée lorsque la variable est déclarée, et le destructeur exécuté automatiquement lorsque la variable est hors de portée.
D'autres déjà répondu à ce sujet, donc je ne m'étendrai pas.
1. Lors du codage en Java ou en C#, vous utilisez déjà RAII...
MONSIEUR JOURDAIN: Ce qui! Quand je dis: "Nicole, apportez-moi mes pantoufles,
et me donnez mon bonnet de nuit," c'est de la prose?
La PHILOSOPHIE de MAÎTRE: Oui, Monsieur.
MONSIEUR JOURDAIN: depuis plus De quarante ans, j'ai parlé de la prose sans rien y connaître, et je suis bien obligé de vous pour avoir enseigné moi.
- Molière: La Classe Moyenne Gentilhomme, Acte 2, Scène 4
Comme Monsieur Jourdain fait avec de la prose, C# et même Java personnes utilisent déjà RAII, mais dans les voies cachées. Par exemple, le code Java suivant (qui est écrit de la même façon en C# en remplaçant synchronized
avec lock
):
void foo()
{
// etc.
synchronized(someObject)
{
// if something throws here, the lock on someObject will
// be unlocked
}
// etc.
}
... est déjà à l'aide de RAII: Le mutex acquisition se fait dans le mot-clé (synchronized
ou lock
), et de l'onu-l'acquisition se fait au moment de la sortie de la portée.
C'est tellement naturel dans sa notation il nécessite presque pas d'explication, même pour les personnes qui n'ont jamais entendu parler de RAII.
L'avantage du C++ a plus de Java et C# ici, c'est que tout peut être fait en utilisant le RAII. Par exemple, il n'existe pas de construire-dans l'équivalent d' synchronized
ni lock
en C++, mais on peut encore les avoir.
En C++, il serait écrit:
void foo()
{
// etc.
{
Lock lock(someObject) ; // lock is an object of type Lock whose
// constructor acquires a mutex on
// someObject and whose destructor will
// un-acquire it
// if something throws here, the lock on someObject will
// be unlocked
}
// etc.
}
ce qui peut facilement être écrite en Java/C# chemin (à l'aide de C++ macros):
void foo()
{
// etc.
LOCK(someObject)
{
// if something throws here, the lock on someObject will
// be unlocked
}
// etc.
}
2. RAII ont d'autres utilisations
LAPIN BLANC: [en chantant] je suis en retard je suis en retard Pour une date très importante. / Pas le temps de dire "Bonjour." / Au revoir. / Je suis en retard, je suis en retard, je suis en retard.
- Alice au pays des Merveilles (Disney version, 1951)
Vous savez, quand le constructeur sera appelé (à l'objet de la déclaration), et vous savez quand son correspondant destructeur sera appelé (à la sortie de la portée), de sorte que vous pouvez écrire presque magique, code avec, mais une ligne. Bienvenue au C++ pays des merveilles (au moins, à partir d'un développeur C++, du point de vue).
Par exemple, vous pouvez écrire un objet compteur (je laisse ça comme un exercice) et de l'utiliser simplement en déclarant la variable, comme le verrou de l'objet ci-dessus a été utilisé:
void foo()
{
double timeElapsed = 0 ;
{
Counter counter(timeElapsed) ;
// do something lengthy
}
// now, the timeElapsed variable contain the time elapsed
// from the Counter's declaration till the scope exit
}
ce qui, évidemment, peut être écrite, encore une fois, la Java/C# utilisant une macro:
void foo()
{
double timeElapsed = 0 ;
COUNTER(timeElapsed)
{
// do something lengthy
}
// now, the timeElapsed variable contain the time elapsed
// from the Counter's declaration till the scope exit
}
3. Pourquoi est-ce que C++ manque finally
?
[En CRIANT] C'est la finale de compte à rebours!
- Europe: Le compte à Rebours Final (désolé, j'étais hors de citations, ici... :-)
L' finally
clause est utilisée en C#/Java pour gérer les ressources de l'élimination dans le cas de l'étendue de sortie (que ce soit par le biais d'un return
ou la levée d'une exception).
Astucieux spécification lecteurs auront remarqué C++ n'a pas de clause finally. Et ce n'est pas une erreur, parce que le C++ n'en a pas besoin, comme RAII déjà de gérer des ressources de l'élimination. (Et croyez-moi, l'écriture d'un destructeur C++ est des magnitudes de plus facile que d'écrire le droit de Java clause finally, ou même un de C#correcte méthode dispose).
Encore, parfois, une finally
clause serait cool. On peut le faire en C++? Oui, nous le pouvons! Et encore avec une utilisation alternative de RAII.
Conclusion: RAII est plus qu'une philosophie en C++: C++
RAII? C'EST LE C++!!!
- Développeur C++ est indigné commentaire, copié sans vergogne par un obscur Sparte roi et de ses 300 amis
Lorsque vous atteignez un certain niveau d'expérience en C++, vous commencez à penser en termes de RAII, en termes de construtors et destructeurs à l'exécution automatique.
Vous commencez à penser en termes de portées, et l' {
et }
caractères sont ceux des plus important dans votre code.
Et presque tout se tient droit en termes de RAII: l'exception de la sécurité, mutex, de connexions de base de données, base de données des demandes de connexion au serveur, les horloges, les OS poignées, etc., et le dernier, mais pas moins, de mémoire.
La base de données n'est pas négligeable, que, si vous acceptez de payer le prix, vous pouvez même écrire dans un "transactionnelle, la programmation de" style", de l'exécution des lignes et des lignes de code jusqu'à ce que de décider, en fin de compte, si vous voulez enregistrer toutes les modifications, ou, si pas possible, en ayant toutes les modifications qui revient (à condition que chaque ligne satisfaire au moins à la Forte Exception de Garantie). (voir la deuxième partie de cette plante Sutter article pour le transactionnel de programmation).
Et comme un puzzle, tout se tient.
RAII est tellement partie de C++, C++ pourrait ne pas être en C++ sans elle.
C'est ce qui explique pourquoi connu les développeurs C++ sont tellement épris avec RAII, et pourquoi RAII est la première chose que l'on recherche lorsque l'on essaie une autre langue.
Et il explique pourquoi le Garbage Collector, tandis qu'un magnifique morceau de la technologie en elle-même, n'est pas si impressionnant à partir d'un développeur C++, du point de vue:
- RAII déjà gère la plupart des cas, pris en charge par un GC
- Un GC traite mieux que RAII avec des références circulaires sur pur objets gérés (atténué par smart utilise de la faiblesse des pointeurs)
- Encore UN GC est limitée à la mémoire, alors que RAII peut gérer n'importe quel type de ressource.
- Comme décrit ci-dessus, RAII peut faire beaucoup, beaucoup plus...