2016-12-29 4 views
3

J'écris un simple serveur de chat et je me demande quel type de données dois-je utiliser pour un tampon. Je pensais à string (ce qui serait très confortable dans mon cas), mais de nombreuses fois j'ai vu des gens écrire que string ne devrait pas être utilisé comme un tampon (mieux vaut utiliser vector<char>) mais est-ce toujours le cas?Quel type de données dois-je utiliser comme tampon?

Dans mon programme, je voudrais lire un message du client dans un tampon, envoyer ces données à un autre client et également stocker ce message dans la base de données. J'utilise SQLite donc, avec string (sauter l'initialisation db), il ressemblerait à ceci:

std::string buffer; 
buffer.resize(1024); 

// read some data into the buffer 
socket.async_read_some(boost::asio::buffer(&buffer[0], 1024), 
    [this, self](boost::system::error_code ec, size_t length) 
{ 
    buffer.resize(length); 

    // do some other things with buffer - send to another user ... 

    std::string query = "INSERT INTO messages (message) VALUES (\"" + buffer "\")"; 

    sqlite3_exec(database, query.c_str(), sql_callback, NULL, &err_msg); 
} 

Si je devais utiliser vector<char> à la place, il me faudrait tout d'abord pour le convertir en une chaîne (ou peut-être il y a une autre façon ?)

Alors, que dois-je utiliser?

+0

En fait, je ne répondrais pas à votre question, mais je penserais aussi à la conformité UTF-8 et à l'injection sql (vous avez probablement pris cela en compte). Dans mon expérience, en traitant les entrées des utilisateurs, 'wstring' évitait beaucoup de problèmes avec les clients. –

+1

Pour moi, cela dépend de la façon dont vous lisez les données et comment le tampon va être utilisé. Mais si cela va se terminer dans un 'std :: string' et que vous pouvez lire directement dans cette chaîne alors j'utiliserais juste un' std :: string'. J'aurais tendance à utiliser un 'std :: vector ' pour les données binaires ou un tampon temporaire lors de la lecture dans une chaîne (ou quelque chose d'autre). – Galik

+0

Pourriez-vous s'il vous plaît fournir le code qui lit les données dans le tampon? –

Répondre

2

Si votre cas d'utilisation nécessite la plupart du temps une "conversion" vers std::string, il peut être judicieux d'utiliser simplement std::string. La différence la plus évidente entre l'utilisation de std::string en tant que tampon de caractère et std::vector<char> est que le premier est autorisé à faire un peu de magie Optimisation de chaîne courte (dépend du fournisseur de bibliothèque). Alors que ce dernier n'est pas autorisé à le faire. Votre kilométrage peut varier.

Si je devais utiliser vector<char> à la place, il me faudrait d'abord convertir en une chaîne (ou peut-être il y a une autre façon?)

Oui vous devez faire un std::vector<char> à std::string « conversion » comme ceci:

std::string query = "INSERT INTO messages (message) VALUES (\"" + std::string(buffer.begin(), buffer.end()) + "\")"; 

Avec un peu de travail, vous pouvez éviter de créer (et plusieurs temporaires des allocations de mémoire) résultant à la fois du tampon « conversion » et concaténation en utilisant std::string::operator +.

std::string build_query(const char* left_string, std::size_t left_string_size, 
         const std::vector<char>& buffer, 
         const char* right_string, std::size_t right_string_size) 
{ 
    std::string query; 
    query.reserve(left_string_size + buffer.size() + right_string_size + 1); 
    query.append(left_string); 
    query.append(buffer.begin(), buffer.end()); 
    query.append(right_string); 
    return query; 
} 

Et utiliser comme:

std::vector<char> buffer(24); 

constexpr char left[] = "INSERT INTO messages (message) VALUES (\""; 
constexpr char right[] = "\")"; 
std::string query = build_query(left, len(left), buffer, right, len(right)); 

Voir un exemple complet ici: Live On Coliru

Sur le long terme, vous pouvez aller plus loin et écrire quelques aides de modèle soignées pour couvrir les cas plus généraux de construire une chaîne de requête à partir de std::vector<char>.

En ce qui concerne les performances, vous devrez mesurer. Bien que, bien que n'étant pas une mesure valide de la performance, GCC et Clang emits fewer assembly instructions réellement pour build_query que la "conversion" régulière.