Есть ли способ различить возвращаемое значение new и new []? - PullRequest
3 голосов
/ 03 июня 2011

Рассмотрим этот код:

int *p = new int;
cout << sizeof(*p);
delete p;

Как и ожидалось, результат равен 4. Теперь рассмотрим этот другой код:

int *p = new int[10];
cout << sizeof(*p);
delete[] p;

Я ожидал получить 40 (размер выделенного массива), однако результат все равно 4 .

Теперь предположим, что у меня есть функция int *foo(), которая возвращает указатель на структуру, созданную с помощью new или new[] (но я не знаю, какая именно):

int *p = foo();

У меня вопрос, есть ли способ (или хак) узнать, указывает ли p одно целое число или массив целых чисел?

Пожалуйста, имейте в виду, что это всего лишь теоретический вопрос. Я не буду писать реальный код таким способом.

Ответы [ 7 ]

4 голосов
/ 03 июня 2011

Нет, это невозможно сделать. Но вы знаете разницу, потому что код, который вы написали, называется new или new[].

Причина, кстати:

 cout << sizeof(*p);

дает вам 4 в обоих случаях, потому что p это указатель на int, выражение * p означает, что указатель указывает на такой указатель (то есть int), а размер int на вашей платформе равен 4. Это все оценивается во время компиляции, поэтому, даже если new[] вернул специальное значение, sizeof не сможет его использовать.

3 голосов
/ 03 июня 2011

Нет, потому что ваш результат - адрес (вот почему вы получаете 4 для sizeof () в обоих случаях). Вы создали его, поэтому вы должны знать, что это такое.

2 голосов
/ 03 июня 2011

sizeof (x) возвращает объем памяти, необходимый для хранения x, как объявлено.

В этом нет никакого динамического аспекта.

sizeof (* foo), где foo это bar *, всегда будет таким же, как sizeof(bar)

2 голосов
/ 03 июня 2011

В обоих примерах тип p одинаков: int *.sizeof работает с типом, а не с данными.Он вычисляется во время компиляции.

У вас есть несколько вариантов.Вы можете самостоятельно отслеживать размер массива или можете использовать один из контейнеров в стандартной библиотеке, например vector .Эти контейнеры будут отслеживать размер (например, vector :: size ()) для вас.

1 голос
/ 03 июня 2011

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

return new int[1];
1 голос
/ 03 июня 2011

Нет, нет никакого способа.

Обязательный вопрос: зачем вам это знать?

Если это так, потому что мне нужно знать, говорить ли delete [] или delete ", тогда просто используйте массивы все время, если по какой-то непонятной причине вы не можете понять, какой из них вы использовали в своем собственном коде.

0 голосов
/ 03 июня 2011

Во-первых, sizeof(*p) всегда возвращает значение целому числу, поэтому оно всегда возвращает 4 .

Теперь, как вы можете узнать, указывает ли p на int или int[]?

Нет стандартного пути . Тем не менее, вы можете взломать платформу и узнать ее. Например, если вы попытаетесь напечатать p[-1], p[-2], ..., p[-4] etc. для определенных компиляторов (скажем, в моем случае linux), вы увидите конкретный шаблон в значении этого местоположения. Однако это всего лишь взлом, и вы не можете на него всегда полагаться.

...