2010-06-11 3 views
0

Ищете помощь с массивами и указателями и объяснение того, что я пытаюсь сделать. Я хочу создать новый массив в куче типа Foo *, чтобы впоследствии я мог назначать объекты, которые были созданы else, где этот массив. У меня возникают проблемы с пониманием того, что я создаю, когда я делаю что-то вроде следующего.Массивы и указатели

Foo *(*f) = new Foo*[10]; 

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

(f + 9)->fooMember(); ?????? 

Заранее спасибо.

ответ

3
Foo *(*f) = new Foo*[10]; 

Скобки в декларации не нужны, так это то же самое, как:

Foo **f = new Foo*[10]; 

В любом случае new Foo*[10] выделяет пространство для десяти Foo* с и оставляет их неинициализированным. Он возвращает указатель на начальный Foo* в массиве (нулевой элемент), который вы назначаете f.

Чтобы получить доступ к элементам массива, вы просто использовать индексацию:

f[0] = new Foo; 
f[0]->fooMember(); 

Помните, что все, что вы создаете в new[] должны быть освобождены один раз, когда вы сделали с ним по телефону delete[] на указателе. Например:

delete[] f; 

Это не удалять элементы на которые указывают Foo* с в массиве. Если вы создаете Foo объектов, используя new, вы должны delete их до вы удаляете массив.Например, чтобы освободить элемент мы создали выше:

delete f[0]; 
+0

Спасибо. Если бы я хотел получить доступ к отдельным элементам без использования оператора [], но с арифметикой указателя, как бы это выглядело? – Thomas

+0

@Thomas: 'f [0]' является просто сокращением для '* (f + 0)', поэтому, например, вы можете сделать '(* (f + 0)) -> fooMember()'. –

+0

Спасибо. В каком ролле есть первые скобки с * play? – Thomas

1

Вы можете создать массив указателей, используя следующий код:

Foo** f = new Foo*[10]; 

Затем доступ к элементам с:

f[9]->fooMember(); 

Обязательно убирать потом:

delete[] f; 

Благодарю.

+0

Все правильно, и все же я пропускаю комментарий о том, что если эти три линии склеены в программу без дополнительного кода система будет скорее всего, умрет (поскольку не было создано никаких реальных объектов Foo) –

1

Если у вас есть такая ситуация, вы можете найти следующий фрагмент кода полезный:

Первой инициализация:

Foo** f = new Foo*[10]; 
for (int i = 0; i < 10; i++) { 
    f[i] = new Foo; 
} 

Тогда доступ к каждому элементу в массиве f, который вы просили, но вы не сможете этого сделать, если вы не правильно распределите память для каждого члена, вызвав конструктор, как указано выше:

f[9]->fooMember(); 

Наконец, чтобы держать вещи аккуратно и предотвратить утечку памяти:

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

Вы должны использовать 'std :: for_each' над явно написанными циклами. –

+1

@Billy ONeal - Предполагается, что вы собираетесь использовать STL. Конечно, это почти всегда верно, но это предположение. Цикл for по-прежнему является законным и допустимым C++. –

+0

@Khnle: Правда. Однако, просто потому, что что-то возможно или справедливо, это не значит, что это лучший метод для достижения чего-то. Вызов алгоритмов всегда лучше, чем явные контуры. –

1

Массивы и указатели не очень C++ иш. Как насчет

std::vector<std::shared_ptr<Foo> > f; 
f.push_back(std::make_shared<Foo>(whatever, arguments, you, need)); 
// ... 
f[9]->fooMember(); 
// ... 

Нет ручной очистки не требуется :-)

+0

За исключением, конечно, что shared_ptr еще не является частью стандарта C++. – 2010-06-11 08:26:36

+0

@Neil Да, но я надеюсь, что каждый компетентный программист достаточно умен, чтобы google 'shared_ptr' и найти решение. Если 'std :: shared_ptr' не работает,' std :: tr1 :: shared_ptr' или 'boost :: shared_ptr' должен делать трюк :) – fredoverflow