将中等数量的T*静态强制转换为void*时发生访问冲突

Access violation when static_casting a mid-sized number of T* to void*

本文关键字:转换 void 访问冲突 静态      更新时间:2023-10-16

所以我在中断了一段时间后一直在c++中闲逛。我试图破解一个动态映射类,将std::字符串映射到任何对象类型。根据c++标准的static_casting,指向和来自void*的指针会保留地址。因此,如果我将给定的类型静态转换为一个void指针来存储它,然后再将其静态转换回原始类型的指针,应该不会有任何问题。下面是类的相关内容:

template<class T>
T& get( const std::string& key ) 
{
    return *static_cast<T*>( _data[ key ] );   
}
template < typename T >
void put( const std::string& key, const T& val ) 
{
    T* typePointer = new T( val );       
    _data[ key ] = static_cast<void*>( typePointer );         
}
std::map< std::string, void* > _data;

对于非指针参数,这些方法都工作得很好,我想看看put/get开销与静态类型std::map的开销的比较。但是,当插入大量对象时,我会得到"访问违反读取位置"错误。

// this works
DynamicMap myMap1;    
for (uint i=0; i<100; i++) 
{
    myMap1.put( "mat"+i, MyClass() );
}
// this doesn't
DynamicMap myMap2;
for (uint i=0; i<100000; i++) 
{
    myMap2.put( "mat"+i, MyClass() );
}

自从我接触c++已经有几个月了,所以我对VS2012的异常有些生疏。我不明白为什么在地图中插入大量数字时会发生这种情况……在Debug模式和Release模式之间,生成异常之前的数字会发生变化。

warning: adding 'int' to a string does not append to the string

您的"mat"+i没有创建一个末尾附加i的新字符串,因此您最终弄乱了键。使用"mat" + std::to_string(i) (c++ 11),或者

stringstream ss;
ss << i;
string i_string = ss.str();
myMap2.set( "mat"+i_string, MyClass() );