Заполнение массива указателей, удаление при выходе - PullRequest
1 голос
/ 26 августа 2011

В C ++ допустим, что я создаю массив указателей, и каждый элемент должен указывать на тип данных MyType.Я хочу заполнить этот массив в функции fillArPtr(MyType *arPtr[]).Допустим также, что я могу создавать объекты MyType с помощью функции createObject(int x).Это работает следующим образом:

MyType *arptr[10]; // Before there was a mistake, it was written: "int *arptr[10]"
void fillArPtr(MyType *arptr[])
{
    for (int i = 0; i < 10; i++) 
    {
        MyType myObject = createObject(i);
        arptr[i] = new MyType(myobject);
    }
}

Это лучший способ сделать это?В этой программе, как я должен использовать delete для удаления объектов, созданных с помощью «new» (или я должен использовать delete вообще?)

Ответы [ 6 ]

1 голос
/ 26 августа 2011

Так как вы спросили: "Каков наилучший путь", позвольте мне здесь остановиться и предложить более подходящую для C ++ альтернативу. Поскольку ваш createObject уже возвращает объекты по значению, должно работать следующее:

#include <vector>

std::vector<MyType> fillArray()
{
  std::vector<MyType> res;
  for (size_t i = 0; i != 10; ++i)
    res.push_back(createObject(i));
  return res;
}

Теперь вам не нужно вообще управлять памятью, поскольку выделение и очистка выполняется классом vector. Используйте это так:

std::vector<MyType> myArr = fillArray();
someOtherFunction(myArr[2]);   // etc.
someLegacyFunction(&myArr[4]); // suppose it's "void someLegacyFunction(MyType*)"

Скажите, если у вас действительно есть потребность в ручном управлении памятью и указателях, но желательно с примером использования.

1 голос
/ 26 августа 2011
for (int i = 0; i < 10; i++) 
{
    delete arptr[i];
    arptr[i] = 0;
}

Я предлагаю вам посмотреть на повышение shared_ptr (также в библиотеке TR1)

Уже намного лучше:

 std::vector<MyType*> vec;
 for (int i=0; i<10; i++)
    vec.push_back(new MyType(createObject(i));

 // do stuff

 // cleanup:
 while (!vec.empty())
 {
     delete (vec.back());
     vec.pop_back();
 }

Съемка для звезд:

 typedef boost::shared_ptr<MyType> ptr_t;
 std::vector<ptr_t> vec;
 for (int i=0; i<10; i++)
    vec.push_back(ptr_t(new MyType(createObject(i)));
0 голосов
/ 26 августа 2011

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

MyType **arptr = new MyType[10]; 
void fillArPtr(MyType *arptr[])
{
    for (int i = 0; i < 10; i++) 
    {
        MyType myObject = createObject(i);
        arptr[i] = new MyType(myobject);
    }
}

Если вы сделаете это, не забудьте удалить сам массив из кучи

for ( int i = 0 ; i < 10 ; i++ ) {
    delete arptr[i];
}
delete [] arptr;

Если вы собираетесь использовать вектор и заранее знаете размер массива, вы должны предварительно изменить размер массива. Вы получите намного лучшую производительность.

vector<MyType*> arr(10);
0 голосов
/ 26 августа 2011

Вы можете удалить выделенные объекты, используя delete objPtr.В вашем случае,

for (int i = 0; i < 10; i++) 
{
  delete arptr[i];
  arptr[i] = 0;
}

Практическое правило, которое нужно запомнить: если вы выделяете объект с помощью new, вы должны delete его.Если вы выделяете массив объектов, используя new[N], то вы должны delete[] it.

Вместо того, чтобы вставлять указатели в необработанный массив, посмотрите на std::array или std::vector.Если вы также используете умный указатель, например std::unique_ptr, для хранения объектов внутри std::array, вам не нужно беспокоиться об их удалении.

typedef std::array<std::unique_ptr<MyType>, 10> MyTypeArray;
MyTypeArray arptr;

for( MyTypeArray::iterator it = arptr.begin(), int i = 0; it != arptr.end(); ++it ) {
  it->reset( new MyType( createObject(i++) ) );
}

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

Функция createObject(int x) использует new для создания объектов и возвращает указатель на это ?.В этом случае вам также необходимо удалить это, потому что в этом операторе

new MyType( createObject(i++) )

вы создаете копию объекта, возвращенного createObject, но оригинал затем пропускается.Если вы измените createObject также, чтобы он возвращал std::unique_ptr<MyType> вместо необработанного указателя, вы можете предотвратить утечку.

Если createObject создает объекты в стеке и возвращает их по значению, приведенное вышеработать правильно.

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

0 голосов
/ 26 августа 2011

Используйте массив auto_ptrs, если вам не нужно никуда возвращать массив.До тех пор, пока вы не сделаете копии auto_ptrs, они не будут менять владельца, и они будут освобождать свои ресурсы при выходе из функции с момента ее создания на основе RAII.Он также уже является частью стандарта, поэтому для его использования не нужно повышать его :) В большинстве случаев они бесполезны, но звучит как хороший.

0 голосов
/ 26 августа 2011

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

   for (int i = 0; i < 10; i++)
   {
       delete arptr[i];
       arptr[i] = 0;
   }

Другой способ сделать это - использовать std :: vector.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...