Распределение памяти в C ++ vector <T> - PullRequest
1 голос
/ 17 марта 2012

Ниже приведен лучший «минимальный рабочий пример», который я могу пока построить.Я хотел бы понять, если следующий код утечки памяти.

// Class CTest
class CTest {
  vector<int> Elements;
  CTest (vector<int>&);
  ~CTest ();
};
CTest::CTest (vector<int>& Elements_) {
  this->Elements = Elements_;
}
CTest::~CTest () {
}

// main
int main (int argc, char *argv[]) {
  vector<CTest> V;
  for (auto i = 0; i < 10; i++) {
    vector<int> U;
    for (auto j = i; j < i + 5; j++) U.push_back (j);
    V.push_back (*(new CTest (U)));
  }
  // Do whatever
  return 0;
}

Правильно ли я считаю, что, поскольку нет соответствующего вызова delete для каждого вызова new, эта программа делаетдействительно утечка памяти?

Ответы [ 4 ]

9 голосов
/ 17 марта 2012

Да, есть утечка памяти.push_back копирует свой аргумент, поэтому оригинал теряется навсегда (указатель на него больше не существует).

3 голосов
/ 17 марта 2012

Да, вы правы. Более того, ваш код относится к типу «изо всех сил пытаясь понять его неправильно», поскольку vector уже является динамическим контейнером, и у вас нет причин выполнять другое динамическое выделение для вашего элемента (просто оно скопировано).

Есть еще много способов облажаться. Ни одна из них не является специфической проблемой проектирования C ++, но есть просто предел тому, что язык может помешать вам делать. Еще несколько примеров:

int main(int argc, char **argv)
{
    new double;  // leak
    delete static_cast<void*>(&argc);  // doesn't belong to you
    int a = *static_cast<int const *>(0x42); // not a valid pointer

    { T x; x.~T(); }  // call destructor of non-existent object

    { T y; y.~T(); new (static_cast<void*>(&y) T(); }
                   // impossible to recover from exception in T::T()
}

К счастью, почти всегда очевидно, что вы делаете то, что не должны.

0 голосов
/ 17 марта 2012

Да, это утечка, но только потому, что вы слишком стараетесь.

Использование этого кода для заполнения V вектора

V.push_back(CTest(U));

будет делать то, что нужно, без каких-либо утечек.

Как правило, стандартные контейнеры будут управлять памятью для вас (без утечек).Вам не нужно беспокоиться.

0 голосов
/ 17 марта 2012

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

...