Garantie à vie temporaire en C++?
Ne C++ fournir une garantie pour la durée de vie d'une variable temporaire qui est créé à l'intérieur d'un appel de fonction, mais pas utilisé en tant que paramètre? Voici un exemple de classe:
class StringBuffer
{
public:
StringBuffer(std::string & str) : m_str(str)
{
m_buffer.push_back(0);
}
~StringBuffer()
{
m_str = &m_buffer[0];
}
char * Size(int maxlength)
{
m_buffer.resize(maxlength + 1, 0);
return &m_buffer[0];
}
private:
std::string & m_str;
std::vector<char> m_buffer;
};
Et voici comment l'utiliser:
//this is from a crusty old API that can't be changed
void GetString(char * str, int maxlength);
std::string mystring;
GetString(StringBuffer(mystring).Size(MAXLEN), MAXLEN);
Quand le destructeur de la temporaire de StringBuffer objet appelé? Est-il:
- Avant l'appel à GetString?
- Après GetString retourne?
- Compilateur dépendante?
Je sais que C++ garantit une variable temporaire sera valable aussi longtemps qu'il y a une référence à elle - cela s'applique à des objets parents quand il y a une référence à une variable de membre?
Grâce.
- pourquoi ne pas hériter et de surcharge ou de faire une fonction globale? je serait plus propre et Vous ne voudriez pas avoir à créer une classe ony à l'appel d'un membre.
- Si vous allez l'utiliser, vous devez appeler
m_str.reserve(maxlength)
danschar * Size(int maxlength)
, sinon le destructeur pourrait lancer.
Vous devez vous connecter pour publier un commentaire.
Destructeur pour ce genre de temporaires est appelé à la fin de l'expression. Qui est le plus à l'extérieur de l'expression qui n'est pas partie à une autre expression. C'est, dans votre cas, une fois que la fonction retourne la valeur est évaluée. Donc, il va travailler tout beau.
C'est en fait ce qui rend l'expression de modèles de travail: Ils peuvent garder les références à ce genre de temporaires dans une expression comme
Parce que chaque temporaire durera jusqu'à ce que l'expression
Est évaluée complètement. C'est assez décrites de façon concise dans
12.2 Temporary objects
dans la Norme.printf("%s", strdup(std::string("$$$").c_str()) );
?Je veux dire, sistrdup(std::string("$$$").c_str())
est pris comme l'expression complète, alors le pointeur destrdup
voit, c'est valide. Sistd::string("$$$").c_str()
est une expression complète, alors le pointeur destrdup
voit, c'est valide! Pourriez-vous expliquer un peu plus basé sur cet exemple?printf
est la pleine expression. Ainsi, lestrdup
est inutile de fuite de mémoire -- vous pouvez simplement le laisser imprimer lec_str()
directement.litb la réponse est exacte. La durée de vie de l'objet temporaire (aussi connu comme une rvalue) est lié à l'expression et le destructeur de l'objet temporaire est appelé à la fin de la pleine expression et lorsque le destructeur sur StringBuffer est appelé, le destructeur sur m_buffer sera également appelé, mais pas le destructeur sur m_str puisque c'est une référence.
Remarque que le C++0x change les choses juste un peu, car il ajoute des références rvalue et la sémantique de déplacement. Essentiellement en utilisant une rvalue paramètre de référence (notées avec des &&) je peux 'move', le rvalue dans la fonction (au lieu de le copier) et la durée de vie de la rvalue peut être lié à l'objet qu'il se déplace dans, pas l'expression. Il y a vraiment une bonne blog de la MSVC équipe qui marche à travers ceci en détail et j'encourage les gens à le lire.
Pédagogique exemple, pour déplacer les rvalue est temporaire cordes et je vais vous montrer affectation dans un constructeur. Si j'ai une classe MyType qui contient une chaîne de caractères variable membre, il peut être initialisée avec une valeur r dans le constructeur de la sorte:
C'est bien parce que quand je déclare une instance de cette classe à un objet temporaire:
ce qui se passe, c'est que nous éviter de copier et de détruire l'objet temporaire et "bonjour" est placé directement à l'intérieur de la classe possédant de l'occurrence de variable membre. Si l'objet est plus lourd qu'une "chaîne", puis la copie supplémentaire et destructeur de l'appel peut être importante.
Après l'appel à GetString retourne.
J'ai écrit presque exactement de la même classe:
Standard avant de le chaque compilateur à fait différemment. Je crois que le vieux Annoté Manuel de Référence pour le C++ précisé que temporaires devraient nettoyer à la fin de la portée, de sorte que certains compilateurs fait. Comme la fin de 2003, j'ai trouvé que le comportement existait toujours par défaut sur du Soleil Forte compilateur C++, donc StringBuffer n'a pas fonctionné. Mais je serais étonné si un compilateur actuel était encore que le bris.
StringBuffer est dans le champ d'application de GetString. Il doit être détruit à la fin de GetString du champ d'application (c'est à dire quand il retourne). Aussi, je ne crois pas que le C++ ne garantit qu'une variable existera tant qu'il y est référence de.
Suivantes devraient compiler: