С++, почему нет какой-то длины (массива)?

Ну, я не думаю, что это действительно важно, но поскольку программа должна хранить длину из-за удаления [] в любом случае, почему мы не можем получить эту "сохраненную информацию"?

Ответы

Ответ 1

Реализация требует только сохранения длины и, как правило, только, если тип не является тривиально разрушаемым (т.е. ему нужно генерировать вызовы деструктору), и массив был создан с помощью нового оператора [].

Поскольку это свойство массивного типа не имеет отношения к размеру массива, более элегантно просто называть длину "cookie" частным элементом реализации.

Чтобы получить длину полного объекта массива (а не простого указателя), вы можете использовать std::extent< decltype( arr ) >::value или std::end( arr ) - std::begin( arr ).

Использование new[] с классом с деструктором является запахом кода. Вместо этого рассмотрим std::vector. Накладные расходы по сравнению с raw new[] (с учетом всех байтов, которые должны быть выделены, где бы они ни находились) - это один указатель, стоящий за байты, а преимущества бесчисленны.

Ответ 2

Рассмотрим случай:

char* a = new char[100];

Теперь a должен указывать на буфер, размер которого не менее 100 символов, но для этого может потребоваться более большой буфер.

С учетом этого мы можем видеть, что система может сразу забыть размер запрошенной программы, если он еще может освободить буфер надлежащим образом позже. (Либо путем запоминания размера выделенного буфера, либо выделения памяти с помощью некоторой интеллектуальной структуры данных, где требуется только указатель на начало)

Итак, в общем случае информация, которую вы ищете, фактически не хранится где-либо.

Ответ 3

Не все массивы выделяются new.

void f(int* arr, size_t n)
{
  length(arr);  //  ???
}


int main()
{
  int a[5];
  f(a);
}

Тривиально писать, просто назовите (std::end(arr) - std::begin(arr)), хотя он работает только для массивов, а не для указателей, указывающих на начало массивов.

Ответ 4

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

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

Ответ 5

Для правильных массивов, то есть int a[length], у вас уже есть этот объект: просто сделайте

#define length(A) (sizeof(A) / sizeof(*A))

и вы закончили с ним.

Если вы говорите о том, чтобы получить длину массива, на который указывает указатель, ну, указатели и массивы - это две разные концепции, и их объединение не имеет смысла, даже если соответствующие массивы "распадаются" на указатели, когда это необходимо, и вы получаете доступ массивов через арифметику указателя.

Но даже если мы не будем учитывать это и говорить о технологических аспектах, среда выполнения C++ может не знать, какова длина вашего массива, так как new может полагаться на malloc, который хранит длина массива по-своему, что понимается только free: среда выполнения C++ хранит дополнительную информацию только тогда, когда у вас есть непустые деструкторы. Довольно грязная картина, да?

Ответ 6

потому что он до реализации, где он хранит эту информацию. поэтому нет общего способа сделать длину (массив)

Ответ 7

Длина, безусловно, не сохраняется во всех реализациях. Например, С++ позволяет собирать мусор (например, boehmgc), и многим коллекторам не нужно знать длину. В традиционных распределителях сохраненная длина часто будет больше, чем фактическая длина, т.е. Длина, а не длина.

Ответ 8

Но какова длина массива? Является ли это количеством байтов в массиве или количеством элементов в массиве?

Например: для некоторого класса A размером в 100 байт,

A * myArray = новый A [100];

должна длина (myArray) вернуть 100 или 100 * 100? Кто-то может захотеть 100, кому-то может понадобиться 10000. Таким образом, нет никаких реальных аргументов ни для одного из них.

Ответ 9

Тип С++, который больше всего похож на "массивы" на языках, поддерживающих length(array), std::vector<>, и имеет std::vector<>::size().

Размер простых массивов [] известен компилятору в областях, где размер явно, но их можно передать в области, где размер не известен компилятору. Это дает С++ больше способов обработки массивно-подобных данных, чем языков, которые должны поддерживать length interogative (поскольку они должны гарантировать, что размер всегда передается).