汽车构造函数的指针在VC2008
题
我有一个自动指针实现:
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在Visual C ++ 2005或2008年,我不能没有的东西去可怕的错误从一个函数返回一个指针自动工作正常++ 6.不过。
e.g。
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)的
这导致了温度自动PTR删除存储器和“a”保持一个指针到释放的内存。
然而,在VC6它并调用正确的构造。现在说这一切我也用gcc在Linux和Mac,因此任何代码我写需要太那里工作。 VC2008可以防止您在拷贝构造函数使用值变量非const。此外,我不想要“常量”无论如何,因为拷贝构造取存储器块,其从对象中删除所有权被复制的所有权...从而修改它。
我怎样才能使这项工作在VC 2005/2008?
解决方案
这是否甚至最近克下编译+ +?我想在我的MacBook Pro和:
xxx.cpp: In function ‘AutoString func()’:
xxx.cpp:52: error: no matching function for call to ‘AutoPtr<char, true>::AutoPtr(AutoString)’
xxx.cpp:12: note: candidates are: AutoPtr<T, isArray>::AutoPtr(AutoPtr<T, isArray>&) [with T = char, bool isArray = true]
xxx.cpp:9: note: AutoPtr<T, isArray>::AutoPtr(T*) [with T = char, bool isArray = true]
xxx.cpp:52: error: initializing temporary from result of ‘AutoPtr<T, isArray>::AutoPtr(T*) [with T = char, bool isArray = true]’
这是我能得到这个编译的唯一方法是通过使拷贝构造函数采取const
引用这是我产生了怀疑。它看起来像香草萨特发表的关于他最近GotW非常相似东西这一点。我不会试图复制所有权转移语义std::auto_ptr
没有一个很好的理由。你可能想看看 Boost.SmartPtr <各种好吃的东西/ A>。如果可能的话,用它们来代替。
如果您不能升压无论出于何种原因,然后阅读你喜欢的std::auto_ptr
执行,并特别注意的std::auto_ptr_ref
类。一旦你明白为什么它的存在,它是如何执行它,然后回去写一个自动PTR类。此类存在要解决这个问题,你所看到的问题。 IIRC,这是在一些细节中约祖蒂斯讨论:该标准C ++库。我认为这是我真正理解它的第一次。
其他提示
您可以标记出需要的“明确的”关键字T *参数的构造。我已验证这工作,防止虚假临时对象的创建也提高性能。任何使用该构造函数不能再依赖于编译器的类型转换规则,但。例如,函数会改变这样:
GAutoString Func()
{
char *s = new char[4];
strcpy(s, "asd");
return GAutoString(s);
}
这很烦人,但我不认为这必然是在这种情况下,一件坏事,因为自动类型转换可能会造成混淆。