One of C ++ "ish" methods to solve this problem is to describe the buffer itself as "trivially copied" (C ++ 11 lingo, was a "POD" for "plain old data" in C ++ 98 and 2003) struct, with the microscopic exception that he has a private contructor to prevent instantiation. Then create a pointer object for this structure. Here's a complete but trivial program with this idea:
#include <cstdlib> #include <cstring> struct MyBuffer { int length; char data[1]; private: MyBuffer() {} MyBuffer& operator =(MyBuffer& other) { return other; } }; class MyBufferPointer { MyBuffer *bufptr_; static std::size_t getsize(std::size_t array_size) { return sizeof (MyBuffer) + array_size * sizeof (char); } static MyBuffer *getbuf(std::size_t array_length) { std::size_t sz = getsize(array_length); return static_cast<MyBuffer*>( malloc(sz) ); } public: MyBufferPointer() { bufptr_ = NULL; } MyBufferPointer(std::size_t array_length) { bufptr_ = getbuf(array_length); bufptr_->length = array_length; } MyBufferPointer(const MyBufferPointer &other) { const MyBuffer *op = other.bufptr_; if (op == NULL) { bufptr_ = NULL; } else { bufptr_ = getbuf(op->length); bufptr_->length = op->length; std::size_t sz = op->length * sizeof op->data[0]; std::memmove( bufptr_->data, op->data, sz ); } } MyBufferPointer& operator =(const MyBufferPointer &other) { const MyBuffer *op = other.bufptr_; if (op == NULL) { bufptr_ = NULL; } else { bufptr_ = getbuf(op->length); bufptr_->length = op->length; std::size_t sz = op->length * sizeof op->data[0]; std::memmove( bufptr_->data, op->data, sz ); } return *this; } ~MyBufferPointer() { if (bufptr_) free(bufptr_); } std::size_t size() const { return bufptr_ ? bufptr_->length : 0; } // conventience operations for access to the data array: char &operator [](std::size_t index) { return bufptr_->data[index]; } char at(size_t index) const { return bufptr_->data[index]; } MyBuffer* c_buffer() { return bufptr_; } }; #include <iostream> using namespace std; int main() { MyBufferPointer bufp; cout << "bufp().size() = " << bufp.size() << ", c_buffer=" << bufp.c_buffer() << endl; bufp = MyBufferPointer(100); cout << "bufp().size() = " << bufp.size() << ", c_buffer=" << bufp.c_buffer() << endl; return 0; }
The MyBuffer structure is a layout for the C data region, only with private constructor declarations and assignment statements to prevent instantiation or copy attempts (none of them will work properly, neither in C nor in C ++). The MyBufferPointer class encapsulates this as a C ++ class char [] array, overloading the [] operator.
It still uses malloc (), not the new one. The memory image needed to satisfy the C APIs you mentioned needs a variable-length structure, and you can't get it in the standard C ++ class created by the new one. It just provides a C ++ wrapper to give one point to create the structure in this class (in the static member functions getize () and getbuf ()); and guaranteed buffer deletion when the pointer goes out of scope. You can add resize (), to_string (), substring () or any other methods you want.
Performance should be identical to the C structure, accessible by a regular pointer after optimization, since the methods are declared in the class and are simple enough to be nested.
source share