クラスに関数があり、デバッグモードでもコンパイラにNRVOを常に使用させたいと思っています。このためのプラグマはありますか?
これが「リリース」モードでうまく機能する私のクラスです。
template <int _cbStack> class CBuffer {
public:
CBuffer(int cb) : m_p(0) {
m_p = (cb > _cbStack) ? (char*)malloc(cb) : m_pBuf;
}
template <typename T> operator T () const {
return static_cast<T>(m_p);
}
~CBuffer() {
if (m_p && m_p != m_pBuf)
free(m_p);
}
private:
char *m_p, m_pBuf[_cbStack];
};
このクラスは、_cbStackバイトを超える必要がない限り、スタック上にバッファーを作成するために使用されます。次に、破壊するときに、割り当てられている場合はメモリを解放します。文字列バッファを必要とするc関数とインターフェイスするときに便利であり、最大サイズがわからない場合に便利です。
とにかく、私はこのテストのように、CBufferを返すことができる関数を書き込もうとしていました。
#include "stdafx.h"
#include <malloc.h>
#include <string.h>
template <int _cbStack> CBuffer<_cbStack> foo()
{
// return a Buf populated with something...
unsigned long cch = 500;
CBuffer<_cbStack> Buf(cch + 1);
memset(Buf, 'a', cch);
((char*)Buf)[cch] = 0;
return Buf;
}
int _tmain(int argc, _TCHAR* argv[])
{
auto Buf = foo<256>();
return 0;
}
私はfoo()を高速にするためにNRVOを頼りにしていました。リリースモードでは、うまく機能します。デバッグモードでは、クラスにコピーコンストラクターがないため、明らかに失敗します。CBufferは、すべてを50回コピーしたい開発者によって使用されるため、コピーコンストラクターは必要ありません。(Rant:これらの人は動的配列クラスを使用してWideCharToMultiByte()に渡す20文字のバッファーを作成していました。スタックに文字の配列を割り当てることができることを忘れているようです。彼らはスタックが何であるかさえ知っています...)
コードがデバッグモードで動作するように、コピーコンストラクターをコーディングしたくありません。それは巨大で複雑になります:
template <int _cbStack>
class CBuffer {
public:
CBuffer(int cb) : m_p(0) { Allocate(cb); }
CBuffer(CBuffer<_cbStack> &r) {
int cb = (r.m_p == r.m_pBuf) ? _cbStack : ((int*)r.m_p)[-1];
Allocate(cb);
memcpy(m_p, r.m_p, cb);
}
CBuffer(CBuffer<_cbStack> &&r) {
if (r.m_p == r.m_pBuf) {
m_p = m_pBuf;
memcpy(m_p, r.m_p, _cbStack);
} else {
m_p = r.m_p;
r.m_p = NULL;
}
}
template <typename T> operator T () const {
return static_cast<T>(m_p);
}
~CBuffer() {
if (m_p && m_p != m_pBuf)
free((int*)m_p - 1);
}
protected:
void Allocate(int cb) {
if (cb > _cbStack) {
m_p = (char*)malloc(cb + sizeof(int));
*(int*)m_p = cb;
m_p += sizeof(int);
} else {
m_p = m_pBuf;
}
}
char *m_p, m_pBuf[_cbStack];
};
このプラグマは機能しません:
#pragma optimize("gf", on)
何か案は?