0

バッファを埋める典型的な関数を考えてみましょう:

const char* fillMyBuffer( const char* buf, int size );

この関数が、呼び出しのほぼ直後に使用したい有用なデータでバッファーを満たし、その後バッファーを削除したいとします。

これを行う効率的な方法は、スタックに割り当てることです。

doStuff();

{
    char myBuf[BUF_LEN];
    const char* pBuf = fillMyBuffer( myBuf, BUF_LEN );

    processBuffer( pBuf );
}

doOtherStuff();

したがって、バッファがスタックに割り当てられるため、これは私のライブラリにとって素晴らしいことです。割り当て、使用、および破棄のコストは本質的にありません。それは、包含中括弧の全範囲にわたって続きます。

しかし、私はいつもこのパターンを行うライブラリを持っています。これを少し自動化したい。理想的には、次のようなコードが必要です。

doStuff();

{
    // tricky - the returned buffer lasts the entire scope of the braces.
    const char* pBuf = fillMyBufferLocal();

    processBuffer( pBuf );
}

doOtherStuff();

しかし、これを達成する方法は?

私は次のことを行いましたが、これはうまくいくようですが、標準に反していることはわかっています:

class localBuf
{
public:
    operator char* () { return &mBuf[0]; }
    char mBuf[BUF_LEN];   
};

#define fillMyBufferLocal()   fillMyBuffer( localBuf(), BUF_LEN );

実際問題として、バッファーは、含まれているブレースの有効期間全体にわたってスタック上で存続します。しかし、標準では、オブジェクトは関数が戻るまで存続するだけでよいとされています。たとえば、技術的には、関数内のスタックにバッファを割り当てた場合と同じくらい安全ではありません。

これを達成する安全な方法はありますか?

4

3 に答える 3

1

スタックベースのバッファを含み、char const * に変換するクラスを書くことができます。

void processBuffer(char const * buffer);
char const * fillMyBuffer(char const * buffer, int size);
int const BUF_LEN = 123;

class Wrapper
{
public:
  Wrapper(char const * (*fill)(char const *, int))
  {
    fill(&m_buffer[0], m_buffer.size());
  }

  operator char const * () const { return &m_buffer[0]; }

private:
  std::array<char, BUF_LEN> m_buffer;
};


void foo()
{
  Wrapper wrapper(fillMyBuffer);

  processBuffer(wrapper);

}
于 2013-04-25T15:36:33.760 に答える