проблема с выделением памяти для вектора члена класса, учитывая массив объектов этого класса? - PullRequest
1 голос
/ 20 февраля 2011

Моя основная структура программы такова:

class B1 
{
    vector <someStruct> aStruct; //some struct contains a vector of 'someotherStruct's, etc
    B1() { cout << &aStruct << " ";};
};


class B2 {B1* pB1;};

class A
{
    B1 object_B1;
    B2 object_B2;

    A() { objectB2.pB1 = &object_B1;}; 
};

int main()
{
    vector <A> someA;
    for(int q=0; q < N; q++)
        someA.push_back(A()); 

    cout << endl;

    for (int q=0; q < N; q++)
        cout << someA[q].B2.pB1 << " ";
}

Так что, если бы N было 5, результат будет: 0xbffff828 0xbffff828 0xbffff828 0xbffff828 0xbffff828 \ n
0xbffff828 0xbffff828 0xbffff828 0xbffff828 0xbffff828

Другими словами, вектор каждого объекта занимает одно и то же место в памяти. И вывод программы также подтверждает это, поскольку доступ к данным в векторе через разные объекты дает одинаковые значения, даже если они должны быть разными. Другая странная вещь, конечно, в том, что она дает мне тот же адрес для вектора, что и для объекта.

Ответы [ 2 ]

3 голосов
/ 20 февраля 2011

Игнорирование большого количества ошибок в программе ...

A.push_back(A());

Это создает временный объект типа A. Переменная-член object_B2.pB1 инициализируется так, чтобы указывать на переменную-член object_B1 этого временного объекта.

Этот временный A объект затем копируется в контейнер someA. Адрес переменной-члена object_B1 этой копии отличается, но вы не обновите переменную-член object_B2.pB1, чтобы она указала на новый экземпляр. Для этого вам потребуется реализовать конструктор копирования (и, для правильности, вам также потребуется реализовать оператор присваивания копии).

Причиной того, что все указатели оказываются одинаковыми, является то, что все временные объекты создаются в одном и том же месте в памяти. может быть создан в стеке в одном и том же месте на каждой итерации цикла.

2 голосов
/ 20 февраля 2011

Вам не хватает ctor для A, и семантика копирования по умолчанию копирует значение указателя из одного объекта B2 в другой.Каждый элемент в структуре видит один и тот же адрес, потому что все они скопированы из одного и того же исходного объекта.Когда этот указанный объект будет позже уничтожен, у вас будет доступ к нему UB.

A a1;
A a2 = a1;
assert(a2.object_B2.pB1 == &a1.object_B1);  // Danger Will Robinson!

Исправление:

struct A {
  B1 object_B1;
  B2 object_B2;

  A() { objectB2.pB1 = &object_B1; }
  A(A const &x)
  : object_B1 (x.object_B1)
  {
    object_B2.pB1 = &object_B1;
  }
};

Вам также понадобится оператор назначения копирования, потому что по умолчаниюу одного есть похожая проблема.Объявите эту опцию как частную, не определяя ее, если хотите, чтобы она была отключена.

...