gpt4 book ai didi

复制后访问对象时 C++ 程序崩溃

转载 作者:行者123 更新时间:2023-11-30 01:54:27 24 4
gpt4 key购买 nike

我遇到了一个问题,我认为它与创建对象的拷贝有关。我有一个 map 类,其中包含一个 std::map,其中有一堆类定义了由其 ID 索引的不同图 block 类型,以及 vector 中的一堆图 block ,每个图 block 都有一个指向其中一个类的指针。此外,我还有另一个包含 map 的类 Scenario。

当我创建一个 Scenario 对象并尝试对其 map 执行任何操作时,问题就来了。复制指针时一定有问题,但我一直无法弄清楚。

我已尝试将代码减少到重现问题所需的代码:

#include <string>
#include <map>
#include <vector>
#include <iostream>

using namespace std;

class TileInfo {
string name;

public:
int id;
TileInfo() {};
TileInfo(int id, string name);

string getName() const;
};

TileInfo::TileInfo(int id, string name)
{
this->id = id;
this->name = name;
}

string TileInfo::getName() const
{
return name;
}

class Tile
{
public:
TileInfo* info;

Tile() {};
Tile(const Tile & other, map<int,TileInfo> & info);
Tile (TileInfo* info);

string getName() const;
};

Tile::Tile (TileInfo* tileInfo)
{
this->info = tileInfo;
}

Tile::Tile( const Tile & other, map<int,TileInfo> & tileInfo )
{
map<int,TileInfo>::iterator it = tileInfo.find(other.info->id);

if(it == tileInfo.end())
this->info = NULL;
else
this->info = &(it->second);
}

string Tile::getName() const
{
return info->getName();
}

class Map
{
vector <vector <Tile>> tiles;
map <int, TileInfo> tileInfo;

public:
void print() const;

Map() {};
Map(map<int,TileInfo> tileInfo);
Map(const Map & other);

string getName() const;
void loadTiles();
};

Map::Map(map<int,TileInfo> tileInfo)
{
this->tileInfo = tileInfo;
}

Map::Map(const Map & other)
{
this->tileInfo = other.tileInfo;

for(unsigned int i = 0; i < other.tiles.size(); i++)
{
vector<Tile> line;

for(unsigned int j = 0; j < other.tiles[i].size(); j++)
{
Tile tmpTile = Tile(other.tiles[i][j],tileInfo);
line.push_back(tmpTile);
}

this->tiles.push_back(line);
}
}

void Map::print() const
{
for(unsigned int i = 0; i < tiles.size(); i++)
{
for(unsigned int j = 0; j < tiles[i].size(); j++)
{
cout << "Tile at " << i << ", " << j << " is a "; cout << tiles[i][j].getName() << endl;
}
}
}

void Map::loadTiles()
{
for(unsigned int i = 0; i < 3; i++)
{
vector <Tile> line;
for(unsigned int j = 0; j < 3; j++)
{
map<int,TileInfo>::iterator ite = tileInfo.find(i);
if( ite!=tileInfo.end())
line.push_back(Tile(&(ite->second)));
else
{
line.push_back(Tile(NULL));
}
}

tiles.push_back(line);
}
}

class Scenario
{
public:
Map map;
Scenario() {};
Scenario(Map map);
};

Scenario::Scenario(Map map)
{
this->map = map;
this->map.print();
}

Map createMap()
{
map<int,TileInfo> tmpInfo;

for(unsigned int i = 0; i < 3; i++)
{
tmpInfo.insert(pair<int,TileInfo>(i,TileInfo(i,"testname")));
}

Map rtrnVal = Map(tmpInfo);

rtrnVal.loadTiles();

return rtrnVal;
}

int main()
{
Map newMap = createMap();

Scenario newScenario = Scenario(newMap);
newScenario.map.print();
int input;
cin >> input;
}

Scenario 构造函数末尾的 print() 正确打印了 map 的内容,但分配场景后的那个会导致崩溃。任何帮助将不胜感激。

最佳答案

存储原始 TileInfo 对象的原始 std::map 位于此处:

map<int,TileInfo> tmpInfo;

for(unsigned int i = 0; i < 3; i++)
{
tmpInfo.insert(pair<int,TileInfo>(i,TileInfo(i,"testname")));
}

那是两对房子所在的 map 。然后你复制一张 map 。它会创建所有 TileInfo 对象的拷贝,这没问题。

Map rtrnVal = Map(tmpInfo);

但这是轮子开始脱落的地方。您在此处触发 loadTiles,它会设置您的 vector 图,以在 rtrnVal 中寻址相关的 TileInfo 对象。这段代码:

rtrnVal.loadTiles();

导致此代码。请注意,您正在将映射的 TileInfo 对象的地址推送到 vector 中。这些所在的 map 是这个对象 map 。

void Map::loadTiles()
{
for(unsigned int i = 0; i < 3; i++)
{
vector <Tile> line;
for(unsigned int j = 0; j < 3; j++)
{
map<int,TileInfo>::iterator ite = tileInfo.find(i);
if( ite!=tileInfo.end())
line.push_back(Tile(&(ite->second)));
else
{
line.push_back(Tile(NULL));
}
}

tiles.push_back(line);
}
}

最后,回到我们开始的地方,你这样做:

return rtrnVal;

这会生成 Map 的拷贝,这会生成 vector map 的拷贝,其中包含指向 TileInfo 的指针rtrnVal 中的映射将在函数退出时被销毁。结果返回调用方。

Map newMap = createMap(); 

newMap 现在包含指向 createMaprtrnVal 中的 TileInfo 对象的悬垂指针。

可能的解决方案

与其拥有一个包含指向 TileInfo 指针的 vector 映射,不如考虑一个包含索引的 vector 映射,其中每个索引键指向一个从 0 开始的插槽TileInfo std::vector 包含在 map 旁边。我可以看到您正在尝试做什么(跨多个单元格共享的单个 TileInfo),因此您仍然可以从中受益。无论 map 在哪里(它们属于同一个 Map 对象), vector 都会随行,并且复制不会造成任何损害,因为 map (索引)和 vector (的TileInfo) 将安全复制。最后你仍然得到你想要的(单数 TileInfos)但是现在用数字而不是指针索引。作为奖励,您不必在自定义复制构造器中处理将指向 TileInfo 的指针从一张 map rebase 到另一张 map 。它都是相对的 (0.. n-1)

祝你好运。

关于复制后访问对象时 C++ 程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21986264/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com