Search code examples
c++raii

RAII char buffer


I'd like to wrap few C functions for safe C++ usage. There is a C function which takes raw pointer to array and its size, like -

void function(char* bufferToFill, size_t bufsize)

And now, I am having trouble finding C++ object which can expose a raw pointer to be passed to such function. I would like to avoid using new[] and keeping in mind to delete[] it every time I throw an exception.

std::string obviously cant expose its char*, std::vector similar, the only thing that comes to my mind is std::unique_ptr but it feels kinda odd (because its usually used to own an object, not array?)

Whats the proper C++ way to solve such problem? Thanks in advance


Solution

  • std::string obviously cant expose its char*, std::vector similar

    Of course they can; C++11 guarantees the storage for both std::string1 and std::vector to be contiguous, so you can do &str[0] to obtain a pointer to the underlying data (edit: actually for std::vector &str[0] is not ok if str.size()==0, however the data() method is guaranteed to work always).

    The validity of the pointer is subject to the usual references invalidation rules (i.e. it's valid as long as you don't perform any potentially reallocating operation).

    Corner case: empty containers

    While empty containers in this case are not an issue (why would someone pass a zero-length buffer to fill?) it's still useful to know that:

    • for std::string, it's always safe to ask for &str[0], even if the string is empty; in facts, the standard says explicitly (at [string.access]):

      Returns: *(begin() + pos) if pos < size(), otherwise a reference to an object of type T with value charT(); the referenced value shall not be modified.

    • for std::vector, probably it's not ok to call &str[0] if the vector is empty; operator[] is specified in the general requirements for sequence containers, with operational semantic *a.begin(), which is undefined behavior if size() is 0; however, C++11 does provide the data() method, which always returns some kind of valid pointer (although to an empty valid range in the case of an empty vector)

    Unfortunately, you cannot just remember that data() is correct for both containers, as for std::string it returns a const pointer exactly as c_str().


    1. In all the answer, where I say std::string I actually refer to any specialization of std::basic_string.