如果CArray需要增长,则CArray中的std :: set不起作用

时间:2019-11-20 15:33:32

标签: c++ stl mfc c++17 atl

CArray集合中,我必须拥有一个std::set,并且我发现如果CArray需要增长, 它首先崩溃到现有集合而崩溃。因为CArray使用memcpy

有可复制的代码; (VS2019 16.3.8调试x64 / x86)

  std::vector<std::set<int>> _vector;
  _vector.emplace_back();
  _vector.shrink_to_fit();
  _vector[0].emplace(1);
  _vector[0].emplace(2);
  _vector[0].emplace(3);
  _vector.emplace_back();
  _vector[0].emplace(4);
  _vector[0].emplace(5);

  CArray<std::set<int>> _atlarray;
  _atlarray.Add({});
  _atlarray.FreeExtra();
  _atlarray[0].emplace(1);
  _atlarray[0].emplace(2);
  _atlarray[0].emplace(3);
  _atlarray.Add({});
  _atlarray[0].emplace(4);
  _atlarray[0].emplace(5);
std::set中的

std::vector当然可以工作,因为如果元素类型不是很简单的话,则会调用现有元素的层次构造函数。但是我不能将其用于向后兼容。 (CArray已序列化,我不想更改它)

作为解决方案,我可以使用:CArray<std::unique_ptr<std::set<int>>>,但是我的问题是;

  • 在发行版本中不会崩溃,为什么?我是否需要在发布版本中测试更长的时间才能崩溃?还是行得通,而且仅仅是调试问题?
  • 是否有更好的解决方法?
  • 我担心,在解决方案(40个项目)中,我们有相同的问题,但尚未发生。对于将来和现有代码中的相同实现,CArray是否有修复程序?

编辑:有关为何不引导向量的更多说明: 这是一个使用MFC序列化的25年历史的项目(CArchive) 这个CArray集合是一个类的现有集合(在这个类中,我现在添加了这个集合),该集合已经在使用中,并且对其进行了过多的更改。可以改变该集合的序列化等等。 但是在最近的7年中,新添加的代码使用了stl,不幸的是,它是mfc和stl的混合。 如果这是我唯一需要解决的问题,那不是问题。 我只是不知道是否还有另一个相同的问题。我想知道实际上是否有办法修复CArray(通过使用固定的数组类重新定义CArray)

编辑: std :: vector这样做;

template <class _InIt, class _Alloc>
_Alloc_ptr_t<_Alloc> _Uninitialized_copy(
    const _InIt _First, const _InIt _Last, _Alloc_ptr_t<_Alloc> _Dest, _Alloc& _Al) {
    // copy [_First, _Last) to raw _Dest, using _Al
    // note: only called internally from elsewhere in the STL
    using _Ptrval = typename _Alloc::value_type*;

    auto _UFirst      = _Get_unwrapped(_First);
    const auto _ULast = _Get_unwrapped(_Last);

    if constexpr (conjunction_v<bool_constant<_Ptr_copy_cat<decltype(_UFirst), _Ptrval>::_Really_trivial>,
                      _Uses_default_construct<_Alloc, _Ptrval, decltype(*_UFirst)>>) {
        _Copy_memmove(_UFirst, _ULast, _Unfancy(_Dest));
        _Dest += _ULast - _UFirst;
        (void) _Al;
    } else {
        _Uninitialized_backout_al<_Alloc> _Backout{_Dest, _Al};
        for (; _UFirst != _ULast; ++_UFirst) {
            _Backout._Emplace_back(*_UFirst);
        }

        _Dest = _Backout._Release();
    }

    return _Dest;
}

和CArray这样;

SetSize()
{
...
        TYPE* pNewData = (TYPE*) new BYTE[(size_t)nNewMax * sizeof(TYPE)];

        // copy new data from old
        ::ATL::Checked::memcpy_s(pNewData, (size_t)nNewMax * sizeof(TYPE),
            m_pData, (size_t)m_nSize * sizeof(TYPE));

        // construct remaining elements
        ASSERT(nNewSize > m_nSize);
        memset((void*)(pNewData + m_nSize), 0, (size_t)(nNewSize-m_nSize) * sizeof(TYPE));
        for( int i = 0; i < nNewSize-m_nSize; i++ )
#pragma push_macro("new")
#undef new
            ::new( (void*)( pNewData + m_nSize + i ) ) TYPE;
#pragma pop_macro("new")

        // get rid of old stuff (note: no destructors called)
        delete[] (BYTE*)m_pData;
        m_pData = pNewData;
        m_nSize = nNewSize;
        m_nMaxSize = nNewMax;
...
}

0 个答案:

没有答案