我正在尝试以下列方式维护快速访问向量:
MyClass.h:
class MyClass{
private:
std::vector<Stuff> myStuffList;
std::tr1::unordered_map<std::string,Stuff*> myStuffListIndex;
...
public:
void addToStuffList(std::string key,Stuff stuff);
};
MyClass.cpp:
...
void MyClass::addToStuffList(std::string name, Stuff stuff){
myStuffList.push_back(stuff);//our man is guaranteed to be at tail
myStuffListIndex[name] = &myStuffList[myStuffList.size()-1];//store
//pointer to object that we just copy-constructed at tail of list
}
Stuff.h:
class Stuff{
private:
std::string name;
public:
Stuff();
Stuff(const Stuff&);
Stuff& operator=(const Stuff&);
...
};
Stuff.cpp:
Stuff::Stuff() : name(""){}
Stuff::Stuff(const Stuff& other){
if(this != &other){
this->name = other.name;
}
}
Stuff& Stuff::operator=(const Stuff& other){
if(this != &other){
this->name = other.name;
}
}
std::string Stuff::getName(){
return name;//exc_bad_access triggered here
}
稍后,当我尝试通过地图访问向量中的项目时,我得到一个明显间歇性的exc_bad_access错误,如下所示:
void methodA(){
Stuff localStuff;
myClassInstance.addToStuffList("mostrecentstuff",localStuff);
}
...
void methodB(){
//different method now, localStuff would be out of scope but
//shouldn't matter since we passed by value in addToStuffList, right?
Stuff* pStuff = myStuffListIndex["mostrecentstuff"];
std::cout << "Hello, my name is " << pStuff->getName() << std::endl;
}
int main(int argc, const char* argv[]){
methodA();
methodB();
}
为什么访问pStuff-&gt; getName()会抛出exc_bad_access?
答案 0 :(得分:1)
std::vector
如何运作?
它有能力。当达到此容量并且您要求插入新项目时,将使用额外存储重新分配内存以保存此项目。 std::vector
然后将其内容从第一个内存位置移动到新分配的位置。
因此,您的设计被破坏了(您需要在每个矢量调整大小时更新地图)。
然后,关于您的测试用例,由于您只执行一次插入,因此指向vector元素的指针仍然有效。但是看看你的addToStuffList()
方法,我看到了:
void MyClass::addToStuffList(std::string name, Stuff stuff){
myStuffList.push_back(ability);//our man is guaranteed to be at tail
myStuffListIndex[name] = &myStuffList[myStuffList.size()-1];//store
//pointer to object that we just copy-constructed at tail of list
}
不应该是:
myStuffList.push_back(stuff);
什么是ability
?
答案 1 :(得分:1)
如PaulMcKenzie所说,可以调整向量的大小,如果是,则可以在不同的地址重新定位。然后所有指向前一个矢量项的指针都会被破坏。
你永远不应该指向std容器中的项目,但是对于vector,你可以保留它们的索引。
你会:
std::vector<Stuff> myStuffList;
std::tr1::unordered_map<std::string,int> myStuffListIndex;
和
myStuffList.push_back(ability);//our man is guaranteed to be at tail
myStuffListIndex[name] = myStuffList.size() - 1;//store
如果您的应用程序是mutithreaded,则必须使用互斥锁保护上面的代码