これに取り組むC++の「っぽい」方法の1つは、バッファ自体を「簡単にコピーできる」(C++11の専門用語で、C++98および2003では「単純な古いデータ」の「POD」であった)構造体として記述することです。インスタンス化を防ぐためのプライベートコンストラクターがあるという微視的な例外。次に、その構造体のポインター オブジェクトを作成します。これは、そのアイデアを備えた完全だが自明なプログラムです。
#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;
}
MyBuffer 構造体は C データ領域のレイアウトであり、プライベート コンストラクターと代入演算子の宣言のみを使用して、インスタンス化またはコピーの試行を防止します (どちらも C または C++ で適切に機能しません)。 MyBufferPointer クラスはそれを C++ としてカプセル化します。スタイル char[] 配列、[] 演算子のオーバーロード。
これは、新しいものではなく、まだ malloc() を使用しています。あなたが言及したC APIを満たすために必要なメモリイメージには可変長構造体が必要であり、newによって作成された標準C++クラスではそれを取得できません。これは、C++ ラッパーを提供して、そのクラス (静的メンバー関数 getsize() および getbuf()) 内で単一の構造体作成ポイントを提供するだけです。ポインターがスコープ外になったときのバッファーの削除を保証します。resize()、to_string()、substring()、または必要なメソッドを追加できます。
メソッドはクラス内で宣言されており、インライン化できるほど単純であるため、パフォーマンスは、最適化後に通常のポインターによってアクセスされる C 構造体と同じになるはずです。