自動ポインターの実装があります。
template <typename T, bool Arr = false>
class GAutoPtr
{
T *Ptr;
public:
typedef GAutoPtr<T, Arr> &AutoPtrRef;
GAutoPtr(T *ptr = 0)
{
Ptr = ptr;
}
GAutoPtr(AutoPtrRef p)
{
Ptr = p.Release();
}
~GAutoPtr() { Empty(); }
operator T*() { return Ptr; }
T *Get() { return Ptr; }
T *operator->() const { LgiAssert(Ptr); return Ptr; }
inline void Empty()
{
if (Arr)
delete [] Ptr;
else
delete Ptr;
Ptr = 0;
}
AutoPtrRef operator =(GAutoPtr<T> p)
{
Empty();
Ptr = p.Ptr;
p.Ptr = 0;
return *this;
}
void Reset(T *p)
{
if (p != Ptr)
{
Empty();
Ptr = p;
}
}
T *Release()
{
T *p = Ptr;
Ptr = 0;
return p;
}
};
typedef GAutoPtr<char, true> GAutoString;
typedef GAutoPtr<char16, true> GAutoWString;
Visual C++ 6 では問題なく動作します。ただし、Visual C++ 2005 または 2008 では、関数から自動ポインタを返すことはできません。
例えば
GAutoString Func()
{
char *s = new char[4];
strcpy(s, "asd");
return s;
}
int main()
{
GAutoString a = Func();
/// a.Ptr is now garbage
}
何が起こるかというと、コンパイラは一時的な GAutoString を作成して関数の戻り値を保持し、それをスタック上の変数 'a' に渡す際に一時変数の演算子 T*() を呼び出し、次に GAutoPtr( T *ptr = 0) コンストラクター、コピー コンストラクターを使用する代わりに: GAutoPtr(AutoPtrRef p)
これにより、temp auto ptr がメモリを削除し、'a' が解放されたメモリへのポインタを保持します。
ただし、VC6 では、適切なコンストラクターを呼び出します。これをすべて言っていると、私は Linux と Mac でも gcc を使用しているので、私が書いたコードはそこでも動作する必要があります。VC2008 では、コピー コンストラクターで非 const by value 変数を使用できません。また、とにかく「const」は必要ありません。コピー コンストラクターがメモリ ブロックの所有権を取得し、コピー中のオブジェクトから所有権を削除するため、オブジェクトを変更するためです。
VC 2005/2008 でこれを機能させるにはどうすればよいですか?