2017-09-19 6 views
0

J'ai une fonction qui retourne un std::string. Je passe cela à printf et créé une fonction d'assistance qui appelle la fonction avec des arguments communs et retourne le pointeur de chaîne c dans le std::string. Je reçois le même pointeur pour chaque appel. Je pense que cela a quelque chose à voir avec la durée de vie temporaire. Je voudrais réparer cela et le rendre sûr, si possible.Plusieurs temporaires std :: string résultant du même pointeur c_str

#include <stdio.h> 
#include <string> 

std::string intToString(int num) { 
    char buf[100]; 
    snprintf(buf, sizeof(buf), "%d", num); 
    return buf; 
} 

const char *helper(int num, int increment) { 
    return intToString((num + increment) * 10).c_str(); 
} 

int main() { 
    for (int i=1; i < 5; i++) { 
    printf("- %d: %3s %3s %3s %3s\n", i, 
      intToString((i + 0) * 10).c_str(), 
      intToString((i + 1) * 10).c_str(), 
      intToString((i + 2) * 10).c_str(), 
      intToString((i + 3) * 10).c_str() 
      ); 
    printf("+ %d: %3s %3s %3s %3s\n", i, 
      helper(i, 0), 
      helper(i, 1), 
      helper(i, 2), 
      helper(i, 3) 
      ); 
    } 
    return 0; 
} 

Sortie:

- 1: 10 20 30 40 
+ 1: 10 10 10 10 
- 2: 20 30 40 50 
+ 2: 20 20 20 20 
- 3: 30 40 50 60 
+ 3: 30 30 30 30 
- 4: 40 50 60 70 
+ 4: 40 40 40 40 
+2

'retour intToString ((num + incrément) * 10) .c_str(); '- le' std :: string' sauvegardant ce pointeur est parti au moment où l'appelant obtient l'adresse. Votre programme appelle un comportement indéfini. La durée de vie du temporaire dans le premier cas s'étend. Dans la seconde, le seul point temporaire retenu est un pointeur qui pend. – WhozCraig

Répondre

4

La valeur de retour de c_str() est uniquement valable tant que l'objet chaîne existe et n'est pas modifiée. Le renvoyer d'un temporaire comme vous le faites dans helper n'est pas correct. Renvoyer un std::string à la place, et seulement utiliser c_str() sur le site où vous avez réellement besoin de l'utiliser comme un c-string.

Pour référence: http://www.cplusplus.com/reference/string/string/c_str/

0

est ici le code équivalent en utilisant uniquement des objets C++ et cours d'eau:

#include <iostream> 
#include <string> 
#include <iomanip> 

std::string helper(int num, int increment) { 
    return std::to_string((num + increment) * 10); 
} 

int main() { 
    for (int i=1; i < 5; i++) { 
     std::cout << "- " << i 
     << ": " << std::setw(3) << std::to_string((i + 0) * 10) 
     << " " << std::setw(3) << std::to_string((i + 1) * 10) 
     << " " << std::setw(3) << std::to_string((i + 2) * 10) 
     << " " << std::setw(3) << std::to_string((i + 3) * 10) 
     << '\n'; 

     std::cout << "+ " << i 
     << ": " << std::setw(3) << helper(i, 0) 
     << " " << std::setw(3) << helper(i, 1) 
     << " " << std::setw(3) << helper(i, 2) 
     << " " << std::setw(3) << helper(i, 3) 
     << '\n'; 
    } 
    return 0; 
} 

résultat attendu:

- 1: 10 20 30 40 
+ 1: 10 20 30 40 
- 2: 20 30 40 50 
+ 2: 20 30 40 50 
- 3: 30 40 50 60 
+ 3: 30 40 50 60 
- 4: 40 50 60 70 
+ 4: 40 50 60 70