在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>>>
,但是我的问题是;
编辑:有关为何不引导向量的更多说明: 这是一个使用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;
...
}