2012-04-30 3 views
0

Я хочу объявить указатель на целочисленный массив в заголовочном файле для моего класса. У меня естьОбъявление указателя на целочисленный массив C++

private: 
int *theName; 

, а затем в конструкторе

theName = new int[10]; 

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

Я думал, что int * theName создал указатель на целое число, а не целочисленный массив, если это создает указатель на целочисленный массив, как вы создаете указатель на целое число?

Также в деструкторе можно назвать

delete theName; theName = NULL; 

Будет ли удалить theName целочисленный массив объектов, а затем указать theName в нуль в памяти?

Благодаря

+1

Если у вас нет действительно веской причины для этого, вы должны просто использовать 'std :: vector'. –

+0

, возможно, не выполняет выделение кучи с таким малым массивом. – chikuba

ответ

5

Четыре вещи:

  • Один, да это, как вы делаете указатель на массив. Обратите внимание, что нет никакой разницы между указателем на целое число и указателем на целое число массив; вы можете представить себе целое число как массив одного элемента. Вы все равно можете использовать x[0], если x является указателем на целое число, и вы все равно можете использовать *x, если x - указатель на массив, и они работают одинаково.

  • Во-вторых, вы должны использовать delete[] theName, неdelete theName. Где бы вы ни использовали new, вы должны использовать delete, и везде, где вы используете new[], вы должны использовать delete[]. Кроме того, нет необходимости устанавливать theName = NULL, поскольку после запуска деструктора вы все равно не можете получить доступ к theName.

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

  • В-четвертых, если вы просто не делаете это как дидактическое упражнение, вы должны действительно использовать std::vector. Он имеет много преимуществ и никаких реальных недостатков. И вам даже не нужно писать четыре других конструктора, если вы используете vector.

+5

Ненависть быть педантом, но это -> * «нет никакой разницы между указателем на целое число и указателем на целочисленный массив» * неверно. * Я * знаю, что вы имеете в виду, но OP, вероятно, этого не делает, и этот момент может смутить его позже, если он возьмет то, что вы говорите буквально. –

+0

спасибо !! Это действительно помогает и действительно ясно! – JDN

+0

@BenjaminLindley трудно попасть в это, не написав что-то огромное и отвлекающее, которое отвлекает от остальной части ответа, потому что оно настолько детализировано и запутанно для новичков. Но да, это не точно. –

1

Да, это сработает.

Вам необходимо написать delete[] theName - если вы выделили new TYPE[], то вы должны удалить с помощью оператора delete[].

Установка theName в нуль является хорошей формой, хотя и избыточной в деструкторе, поскольку весь объект (и, следовательно, theName) скоро прекратит свое существование.

Лучшим подходом на С ++ может быть использование std::vector<int>.

0

Да, так вы должны инициализировать указатель. У вас есть какие-то проблемы, хотя:

  1. Вам нужно позвонить delete [] на что вы наделяют new[]. Ваш код не работает должным образом и приводит к UB.

  2. Вам необходимо реализовать конструктор копирования и оператор присваивания. Что произойдет, если этот указатель будет скопирован в другой экземпляр вашего типа? В итоге вы вызовете delete [] на него дважды.

  3. Терминология придираться:

Будет ли удалить theName целочисленный массив объектов, а затем точка theName обнулить в памяти?

Нет, он устанавливает theName в NULL. theName - это переменная, как и любая другая, имеющая значение. Эта переменная является адресом, поэтому при использовании как таковой да, это значение будет числовым значением NULL, что бы это ни было.

0

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

Вы можете использовать std::vector. Это [по большей части] может прорезать в везде, где используется массив и обладает следующими преимуществами:

  1. Нет необходимости беспокоиться об управлении памятью
  2. Изменение размера автоматически, когда необходимо
  3. Можно продолжать использование array[index] синтаксис
  4. Может выполнять проверку границ с помощью метода .at().

Если вы хотите указатель на первый элемент (дать API для C-стиля и т.д.), вы можете использовать:

std::vector<int> vec(10); 

SomeCFunction(&vec[0]); 
0

Да, очень хорошие ответы с удалением [] и вектором и прочим, но имейте это в виду: int * p имеет тип «указатель на int». Это действительно указатель на одно целое число. Однако, если вы разыгрываете это как это p [5], это то же самое, что и выражение * (p + 5). Точно так же работает доступ к массиву. (И почему вы можете неявно преобразовать массив в указатель на свой первый элемент.) Однако есть указатель на тип массива. int (* p) [10] является «указателем на массив из int с размером 10». Однако это не то, что вы хотите. Потому что если теперь вы скажете p [5], это будет означать * (p + 5), который будет обращаться к адресу p + sizeof * p * 5. Но sizeof * p является sizeof int [10], так что там у вас беспорядок. (И, конечно, тип p [5] был бы int [10], так как p является указателем на int [10]) ;-)

3

Я стесняюсь публиковать это вообще, но я надеюсь, что это выиграет Это не проблема.

Чтобы быть педантичным: большинство других ответов неверны: то, что вы создали, - это не указатель на массив.Это указатель на int, который ссылается на начальный элемент массива.

Я стесняюсь публиковать об этом по той простой причине, что это почти наверняка связано с неправильной формулировкой в ​​вашем вопросе - указатель на int почти наверняка то, что вы считали нужным, и это то, что вы действительно получил.

Существует, однако, такая вещь, как указатель на массив. Это редко полезно, потому что когда/если вы выполняете на нем указательную математику (включая подписи), указатель на массив работает с увеличением размера массива, на который он указывает. В вашем случае вы назначаете 10 int с. Вы можете использовать subscriptipting с указателем, чтобы ссылаться на int s в массиве, поэтому theName[0] относится к первым int, theName[1] ко второму int и т. Д. - именно то, что вы обычно хотите.

Вы могли быть в состоянии сделать реальное использование указателя на массив, если вы работали с (например) массивом массивов, и хотели указатель, который будет идти через что целый ряд в то время, так что ptr[0] был первым рядом, ptr[1] второй ряд и так далее. Например:

#include <iostream> 

static const int x = 20; 
static const int y = 10; 

int main() { 
    char data[y][x]; 

    auto ptr_array = &data[0]; 
    char *ptr_char = &data[0][0]; 

    std::cout << "Address of entire array: " << (void *)data << "\n"; 

    std::cout << "char *[0] = " << (void *)ptr_char << "\n"; 
    std::cout << "char *[1] = " << (void *)(ptr_char+1) << "\n"; 

    std::cout << "array *[0] = " << (void *)ptr_array << "\n"; 
    std::cout << "array *[1] = " << (void *)(ptr_array+1) << "\n"; 
    return 0; 
} 

Я изменил эту работу с массивом массивов char (вместо int), чтобы сделать математику немного более очевидной - sizeof(char) == 1 (по определению), так что это немного легче выработать математику. Когда я запускаю этот код на моей машине адрес я получаю:

Address of entire array: 0047FD2C 
char *[0] = 0047FD2C 
char *[1] = 0047FD2D 
array *[0] = 0047FD2C 
array *[1] = 0047FD40 

Как вы можете видеть, ptr[0] содержит адрес массива в целом либо образом. Однако с указателем на char, ptr[1] имеет адрес один больше. Однако указатель на массив содержит адрес 0x40 - 0x2C = 0x14 = 20 больше - который соответствует размеру X, который мы передали массиву (20). Другими словами, у нас действительно есть указатель на массив, а арифметика указателя (или, что то же самое, подписи) на этом указателе работает в терминах целого массива за раз.

Я буду повторять, хотя: по крайней мере, если мы будем игнорировать тот факт, что вы почти наверняка должны быть, используя std::vector вместо этого типа вы хотите и тип вы получили оба pointer to int. Там такой тип, как pointer to array, но это почти наверняка не хочу, чтобы вы действительно хотели.

Смежные вопросы