6

I've been wondering about the following issue: assume I have a C style function that reads raw data into a buffer

int recv_n(int handle, void* buf, size_t len);

Can I read the data directly into an std:string or stringstream without allocating any temporal buffers? For example,

std::string s(100, '\0');
recv_n(handle, s.data(), 100);

I guess this solution has an undefined outcome, because, afaik, string::c_str and string::data might return a temporal location and not necessarily return the pointer to the real place in the memory, used by the object to store the data.

Any ideas?

2 Answers 2

12

Why not use a vector<char> instead of a string? That way you can do:

vector<char> v(100, '\0');
recv_n(handle, &v[0], 100);

This seems more idiomatic to me, especially since you aren't using it as a string (you say it's raw data).

Sign up to request clarification or add additional context in comments.

3 Comments

C++11: recv_n(handle, v.data(), 100);
@Chinasaur: I think a cast is required there, because of the const.
Confusingly, vector::data() is not const but string::data() is.
11

Yes, after C++11.

But you cant use s.data() as it returns a char const*

Try:

std::string s(100, '\0');
recv_n(handle, &s[0], 100);

Depending on situation, I may have chosen a std::vector<char> especially for raw data (though it would all depend on usage of the data in your application).

5 Comments

I think this might not work because s[0] is the same as s.data()[0], which might point to a temporal location.
@FireAphis: No. s[0] is not the same as s.data()[0]. The difference is that if the string uses a copy on write implementation it has to make sure that the string is unique before it returns a reference. That is why s[0] returns a reference to a char and not a reference to a const char. The reason data() returns a const char* is that the string data may be being shared with multiple instances of string. Thus when you do &s[0] you are guaranteed to have a pointer to a contiguous unshared string.
I don't think this is a safe approach either, primarily as I believe that std::string doesn't make any guarantees about storage being contiguous - ofcourse for such a small block, it probably is, however there is no guarantee (unless this is C++x0), @chrisaycock's approach is safer.
@Nim: You are correct. I don't believe the C++03 standard guarantees it. But I believe that C++0x does (because they wanted to be able to pass mutatable string to C-Interfaces) and as part of the analysis they did was to look at current implementations and found that no current implementations of the STL did not use contiguous space for &s[0].
It is indeed guaranteed in C++11. In C++03 it wasn't guaranteed, but it was impracticable to implement a string any other way, so yeah, everyone made it contiguous.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.