I'm writing a simple chat server and I'm wondering what data type should I use for a buffer. I was thinking about string
(which would be quite comfortable in my case), however many times I saw people writing that string
should not be used as a buffer (better to use vector<char>
) but is it always the case?
In my program I would like to read some message from the client into a buffer, send that data to some other client and also store that message in database. I use SQLite so, with string
(skipping db initialization) it would look like this:
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);
}
If I was to use vector<char>
instead, I would firstly need to convert it to a string (or maybe there is another way?)
So what should I use?
If your use-case mostly requires some "conversion" to std::string
, then it may be a good idea to simply use std::string
. The most obvious difference between using std::string
as a character buffer vs std::vector<char>
is that the former is permitted to do some magic Short String Optimization (depends on library vendor). While the latter isn't permitted to do so. Your Mileage May Vary.
If I was to use
vector<char>
instead, I would firstly need to convert it to a string (or maybe there is another way?)
Yes you would have to do a std::vector<char>
to std::string
"conversion" like this:
std::string query = "INSERT INTO messages (message) VALUES (\"" + std::string(buffer.begin(), buffer.end()) + "\")";
With some work, you can avoid creating temporaries (and multiple memory allocations) resulting from both buffer "conversion" and concatenation using 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;
}
And use like:
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) );
See a full example here: Live On Coliru
On the long run, you could go further and write some neat template helpers to cover more general cases of building up query string from std::vector<char>
.
As for performance, you will have to measure. Though, while not a valid measure of performance, GCC and Clang actually emits fewer assembly instructions for build_query
than the regular "conversion".
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加