Это надуманный пример, который иллюстрирует проблему, с которой я столкнулся.По сути, я создаю вектор объектов, затем вектор указателей на объекты, затем печатаю указатели и разыменованные объекты.
#include <vector>
#include <iostream>
using namespace std;
namespace {
struct MyClass {
int* MyInt;
MyClass(int* i) : MyInt(i) {}
};
struct MyBigClass {
vector<MyClass> AllMyClassRecords; // Where I keep the MyClass instances
vector<int> TheInts;
void loadMyClasses();
void readMyClasses();
MyBigClass() {}
};
}
void MyBigClass::loadMyClasses() {
for (int i = 0; i < 10; ++i) {
TheInts.push_back(i); // Create an int
int *j = &TheInts[TheInts.size() - 1]; // Create a pointer to the new int
AllMyClassRecords.push_back(MyClass(j)); // Create a MyClass using pointer
}
}
void MyBigClass::readMyClasses() {
for (vector<MyClass>::iterator it = AllMyClassRecords.begin();
it != AllMyClassRecords.end(); ++it)
cout << it->MyInt << " => " << *(it->MyInt) << endl;
}
int main() {
MyBigClass MBC;
MBC.loadMyClasses();
MBC.readMyClasses();
}
По сути, я хочу создать вектор указателей на другой векторИнтс.Проблема заключается в том, что этот код выводит следующее:
0x97ea008 => 159293472
0x97ea02c => 1
0x97ea040 => 2
0x97ea044 => 3
0x97ea078 => 4
0x97ea07c => 5
0x97ea080 => 6
0x97ea084 => 7
0x97ea0d8 => 8
0x97ea0dc => 9
Кажется, что он работает должным образом, за исключением первого значения, которое, вероятно, является некоторым мусором в памяти.Почему влияет только первое значение?Если мой код не работает, почему он сломан только для первого вставленного указателя?
Обновление: я компилирую это, используя g++
в Ubuntu.Что касается конкретно того, что я делаю, я создаю проход анализа компилятора.Объекты MyClass
содержат информацию об инструкциях, которую я хочу обновить при обнаружении определенных регистров.Номер регистра индексирует вектор векторов, поэтому конкретный номер регистра будет иметь вектор MyClass*s
.Таким образом, если регистр найден, любые MyClass
указатели в векторе будут использоваться для обновления объекта MyClass
, содержащегося в отдельном векторе MyClass
.Поскольку я накапливаю информацию об инструкциях, хранящуюся в объектах MyClass
, и информацию о регистрах, которая должна следовать за указателями MyClass
, я не могу сначала создать весь вектор MyClass
без создания отдельного прохода, которого я хотел бы избежать.
Обновление 2: теперь с картинками ...
Pass Progress inserts... InstRecs (TheInt) and updates... UpdatePtrs (MyClass)
---------------------- ------------------ -----------------------
| => I1: Uses r0, r1 | | InstRec for I1 | | r0: InstRec for I1* |
| I2: Uses r0, r2 | ------------------ | r1: InstRec for I1* |
---------------------- -----------------------
Сначала проход вставляет InstRec с информацией о I1.Он также создает указатели на этот новый InstRec, проиндексированный по номеру регистра.Здесь на самом деле r0 - это вектор одного элемента, который указывает на InstRec для I1, поэтому, если когда-нибудь снова встретится с r0 в последующей инструкции, InstRec для I1 будет обновлен.
Pass Progress inserts... InstRecs (TheInt) and updates... UpdatePtrs (MyClass)
---------------------- ------------------ -----------------------
| I1: Uses r0, r1 | | InstRec for I1 | | r0: InstRec for I1* |
| => I2: Uses r0, r2 | | InstRec for I2 | | InstRec for I2* |
---------------------- ------------------ | r1: InstRec for I1* |
| r2: InstRec for I2* |
-----------------------
Аналогично, второйзапись будет вставлена в InstRecs, а указатели будут добавлены в структуру UpdatePtrs.Поскольку I2 использует r0, другой указатель InstRec помещается в вектор r0.Не показано следующее: когда обнаружено, что I2 использует r0, проход просматривает в структуре UpdatePtrs вектор r0 указателей, следует за каждым указателем на их запись InstRec и обновляет InstRec с новой информацией.
Надеюсь, это проясняет то, что я пытаюсь сделать.Я реализовал предложение, впервые предложенное @MerickOWA, об использовании векторных индексов InstRec, а не указателей InstRec (поскольку, как только InstRecs добавляются в массив, они никогда не перемещаются), и, похоже, теперь это работает.