带有指针的map:错误的值评估
std::map with pointers: wrong value assess
我试图保存到STL映射指针到块对象:
void IO::parseInput(void)
{
map<string, Block*> blocksMap;
//=== Create new block and write it to the vector in database ===
Block tmpBlock (bIndex, bName, bWidth, bHeight);
Block* tmpPointer = db.addBlock(tmpBlock); //addBlock returns pointer to the added Block
tmpPointer->printParams(); // -- here is correct output
blocksMap.insert ( pair<string, Block*>(bName, tmpPointer) );
// === Test hash ===
blocksMap.find("anyLegalStringKey")->second->printParams(); // -- wrong output
}
DB类中的addBlock函数:
Block* DB::addBlock (Block& newBlock)
{
blocks.push_back(newBlock);
Block* ptrToLast = &blocks.back();
return ptrToLast;
}
Block在DB类中的向量:
class DB:
{
private:
//=== Database ===
vector <Block> blocks;
};
问题:在写入映射之前,我使用指针tmpPointer访问对象(我想保存的指针)并打印其所有参数。这个是正确的。然后我把这个指针保存在map中。当我尝试使用特定键的map中查找来访问相同的指针时,我得到了错误的输出(我也打印了所有参数)。
当我尝试访问map中的指针以查找任何存在的键时,可能会导致四种不同的反应:
- 一切正常,我得到正常输出(在我的情况下,我打印所有参数)
- 我得到错误的参数(例如,而不是索引7,我得到21814704)
- 读取输出
- 段错误
有趣的是,对于相同的Block对象,我总是有相同的反应(例如,名称为"g22i"的Block总是不可读的输出)。
向量"块"在db中包含正确的信息之前和之后,我保存指针在地图。
谢谢!
您正在尝试使用指向std::vector
元素的长寿命指针。这是灾难的根源。在vector决定重新分配自身的那一刻,所有这样的指针都将失效。
如果你想使用指向vector元素的指针,你必须确保vector永远不会重新分配。也就是说,你必须提前预留足够的容量来存储所有未来的元素。大多数时候,它不是最优的,违背了使用std::vector
或plain的目的。
也可以使用永远不会使指向其元素的指针失效的容器,如std::list
。但std::list
不支持随机访问。您可以使用std::deque
,它支持随机访问(尽管效率不如std::vector
),并且只要您不将任何内容插入序列的中间,就可以保留元素指针的有效性。
最后,您可以继续使用std::vector
,但要确保在其中存储指向Block
对象的[smart]指针,而不是Block
对象本身。这个想法是为了确保向量重新分配不会导致实际的Block
对象的重新分配。
注:另一个注意事项:当您声明map<string, Block*> blocksMap
时,这种映射的元素具有pair<const string, Block*>
类型(注意额外的const
)。即map<string, Block*>::value_type
实际上是pair<const string, Block*>
。
后来你试图用pair<string, Block*>
参数调用blocksMap.insert
,而blocksMap.insert
实际上期望pair<const string, Block*>
。这可以编译,但它涉及到由std::pair
的转换构造函数执行的从pair<string, Block*>
到pair<const string, Block*>
的隐式转换。这不是最优的性能。这就是为什么一个更好的主意可能是使用map<string, Block*>::value_type
而不是试图手动拼写元素类型
blocksMap.insert ( map<string, Block*>::value_type(bName, tmpPointer) );
- 警告处理为错误这里有什么问题
- "error: no matching function for call to"构造函数错误
- MSVC 在不知道类型的情况下评估上下文(和错误)
- 为什么我的键盘命中是评估错误的
- 表达式未评估为常数两个级别的constexpr函数(编译器错误?)
- 中毒的无效引用和短路表达评估错误或UB
- VS 中的 C++ 17 会导致 C++14 中不存在的变量(重新)评估错误
- gcc 在这个概念定义中是否错误地评估了 std::d eclval ?
- 通过指向成员的指针对嵌套访问进行编译时评估期间出现 GCC 错误
- 未评估上下文中的默认模板参数和 lambda:错误还是功能?
- 为什么我会因Valgrind遇到内存错误?(C ,抽象语法树评估)
- std :: initializer_list:错误c2064:项未评估为0参数的函数
- 测验程序总是评估答案是错误的
- 死亡测试时函数调用的评估错误
- 镶嵌评估着色器链接错误
- 编写C++模板以评估表达式指针错误
- "Cannot call member function ... without object"在未评估的上下文中 - GCC 错误?
- 使用堆栈评估后缀表达式时出现分段错误
- 带有指针的map:错误的值评估
- Clang vs. GCC:未评估上下文中的错误会中断 SFINAE