【发布时间】:2014-08-18 16:40:09
【问题描述】:
我正在尝试将指向 Block 对象的指针 保存到 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;
}
DB类中Block的向量:
class DB:
{
private:
//=== Database ===
vector <Block> blocks;
};
问题: 在写入地图之前,我使用指针 tmpPointer 访问对象(我要保存的指针)并打印其所有参数。这个工作正确。然后我用特定的键将此指针保存在地图中。当我尝试使用带有特定键的 map 中的 find 访问相同的指针时,我得到了错误的输出(我还打印了所有参数)。
当我尝试访问 map 中任何现有键的指针时,可能会导致四种不同的反应:
- 一切正常,我得到正常输出(在我的例子中,我打印所有参数)
- 我得到了错误的参数(例如,我得到了 21814704 而不是索引 7)
- 不可读的输出
- 分段错误
有趣的是,对于同一个块对象,我总是有相同的反应(例如,名称为“g22i”的块总是有不可读的输出)。
db 中的矢量“块”在我将指针保存在地图中之前和之后包含正确的信息。
谢谢!
【问题讨论】:
-
当你
push_back变成一个vector时,vector可以增长,这就需要重新分配。这会使对其元素的引用和迭代器无效。 -
您应该始终检查
.find的结果以确保.find() != blocksMap.end()。取消引用.end()是未定义的行为,它没有找到任何东西,只要你调用->second就取消引用 -
将向量中的块存储为指针,最好是
unique_ptr<Block>。当推回更多时,指向这些块的指针不会改变。或者,将索引存储在地图中,以便在矢量中查找。 -
一般建议:使用智能指针 (std::shared_ptr) 而不是裸指针
标签: c++ pointers memory map reference