返回带有重载运算符的副本

soc*_*cks 5 c++ operator-overloading

我有一个类Foo,我已经重载了+运算符,如下所示:

Foo Foo::operator+(const Bar &b)
{
    Foo copy = (*this);
    if (someCondition) return copy;
    //snip
}
Run Code Online (Sandbox Code Playgroud)

对我来说,这看起来很合理.但是,每当我返回副本时,Visual Studio都会警告我"可能是由于堆损坏"而导致的错误.我做了什么有什么问题吗?

编辑:更新更多信息.

错误消息:

Windows已在sample.exe中触发了断点.

这可能是由于堆的损坏,这表明sample.exe或它已加载的任何DLL中的错误.

这也可能是由于用户在sample.exe具有焦点时按下F12.

输出窗口可能包含更多诊断信息.

复制构造函数:

Foo::Foo(const Foo&p)
{
    some_pointer = p.get_some_pointer();
    some_value = p.get_some_value();
}
Run Code Online (Sandbox Code Playgroud)

它打破的代码:

//within dbgheap.c
    extern "C" _CRTIMP int __cdecl _CrtIsValidHeapPointer(
            const void * pUserData
            )
    {
            if (!pUserData)
                return FALSE;

            if (!_CrtIsValidPointer(pHdr(pUserData), sizeof(_CrtMemBlockHeader), FALSE))
                return FALSE;

            return HeapValidate( _crtheap, 0, pHdr(pUserData) );
    }
Run Code Online (Sandbox Code Playgroud)

Dav*_*eas 3

这种类型的错误通常与同一指针的多次删除(或释放)相关,或者与一些更模糊的情况相关(从一个堆获取并释放到另一堆,但这里可能不是这种情况)。

我要做的第一件事是查看析构函数并检查您是否没有进行浅复制和双重删除。例如使用以下代码:

// buggy!!!
struct test {
    int * data;
    test() : data( new int[5] ) {}
    ~test() { delete [] data; }
    test( test const & rhs ) : data( rhs.data ) {}
    test& operator=( test const & rhs ) {
       data = rhs.data;
    }
};
int main() {
    test t1;          // 5 ints allocated int t1.data
    test t2( t1 );    // no memory allocated, t2.data == t1.data
} // t2 out of scope: t2.~test() => delete t2.data
  // t1 out of scope: t1.~test() => delete t1.data but both are the same: double delete
Run Code Online (Sandbox Code Playgroud)

如果是这种情况,您可以决定是否要进行浅复制或深复制。在第二种情况下,复制构造函数(和赋值运算符)应该分配自己的内存,而在第二种情况下,您必须确保内存不会被释放两次。

与指针一样,最好将资源管理委托给外部(预构建)类。在唯一所有权(和深层副本)的情况下,您可能应该使用std::auto_ptr(或std::unique_ptr在 C++0x 中——或 boost 变体)。在第二种情况下,使用boost::shared_ptr(或std::shared_ptr在C++0x中)将确保数据被共享并且仅删除一次。