renvoyer une chaîne d’une fonction

Je voulais écrire une fonction qui sera multi-plateforme (win32 et linux) et renvoyer une représentation sous forme de chaîne de la date / heure [hh: mm: ss jj-mm-aaaa].

Sachant que je veux juste utiliser la chaîne retournée comme temporaire dans un stream comme ci-dessous:

std::cout << DateTime() << std::endl; 

J’ai envisagé d’écrire une fonction avec le prototype suivant

 const char* DateTime(); 

Si vous retournez un tableau de caractères, vous devez le supprimer une fois que vous avez terminé. Mais je veux juste un temporaire, je ne veux pas avoir à vous soucier de la désallocation de la chaîne.

J’ai donc écrit une fonction qui retourne juste un std :: ssortingng:

 #include  #include  #include  std::ssortingng DateTime() { using namespace std; ssortingngstream ss; ssortingng sValue; time_t t = time(0); struct tm * now = localtime(&t); ss <tm_hour << ":"; ss <tm_min << ":"; ss <tm_sec << " "; ss <tm_mday + 1 << " "; ss <tm_mon + 1 << " "; ss <tm_year + 1900; sValue = ss.str(); return sValue; } 

Je me rends compte que je retourne une copie de la variable de stack dans DateTime. Cela est inefficace dans la mesure où nous créons la chaîne sur la stack DateTime, la remplissons, puis renvoyons une copie et détruisons la copie sur la stack.

La révolution de la sémantique des mouvements c ++ 11 a-t-elle fait quelque chose pour résoudre cette inefficacité – puis-je améliorer cela?

lapin, votre code est très bon code C ++ 11. En C ++ 98/03, votre code sera probablement efficace en raison des optimisations du compilateur, mais ces optimisations ne sont pas garanties. En C ++ 11, ces mêmes optimisations rendront probablement votre retour libre, mais dans le cas contraire, votre chaîne sera déplacée au lieu d’être copiée.

Alors revenez en valeur sans culpabilité! 🙂

Nit mineur:

Il est recommandé de déclarer vos valeurs au moment de la première utilisation, au lieu d’être au sumt d’un bloc:

 ssortingng sValue = ss.str(); return sValue; 

Ou peut-être même:

 return ss.str(); 

Mais ceci est juste une petite nit. Votre code est bon et efficace.

Une autre façon de faire est d’en faire un object fonction avec un introducteur de stream, comme dans:

 struct DateTime() { friend std::ostream& operator<<(std::ostream& os, DateTime) { time_t t = time(0); struct tm * now = localtime(&t); os << now->tm_hour << ":"; os << now->tm_min << ":"; os << now->tm_sec << " "; os << now->tm_mday + 1 << " "; os << now->tm_mon + 1 << " "; os << now->tm_year + 1900; return os; } // Could be converted to a static method, // since DateTime has no internal state std::ssortingng str() const { // the following 3 lines can be replaced by // return boost::lexical_cast(*this); std::ossortingngstream ss; ss << *this; return ss.str(); } operator std::string() const { return str(); } }; 

Ok, je sais que ce n’est pas un fil de discussion et tout ça et que je serai probablement viré à l’envers, mais j’ai vu ce qui suit dans une bibliothèque que j’utilise (ROOT du CERN):

 const char * myfunc(){ static std::ssortingng mystr; /*populate mystr */ return mystr.c_str(); } 

Cela ne fonctionne que si vous savez que personne ne sera jamais assez stupide pour garder le pointeur.

C’est une façon d’avoir un temporaire qui ne fuira pas, quoi qu’il en soit.

Dans un monde sans RVO / NRVO, cela devrait éviter la construction de copie dans une bibliothèque standard antérieure à C ++ 11. Dans une bibliothèque post C ++ 11 avec le constructeur de déplacement pour chaîne, il évite néanmoins que le constructeur de déplacement soit appelé; C’est probablement une petite différence, mais le PO demandait toujours comment faire mieux.

(Et oui je suis d’accord pour dire que l’inheritance de ssortingng est moche mais ça marche.)

 #include  #include  #include  #include  using namespace std; class DateSsortingng : public ssortingng { public: DateSsortingng() : ssortingng() { ssortingngstream ss; time_t t = time(0); struct tm * now = localtime(&t); ss << now->tm_hour << ":"; ss << now->tm_min << ":"; ss << now->tm_sec << " "; ss << now->tm_mday + 1 << " "; ss << now->tm_mon + 1 << " "; ss << now->tm_year + 1900; append(ss.str()); } }; int main() { cout << DateString() << endl; return 0; }