Почему в контейнерах С++ возвращается size_type
, а не int
? Если мы создаем собственные структуры, следует ли нам также рекомендовать использовать size_type
?
Size_t vs int в С++ и/или C
Ответ 1
В общем случае size_t
следует использовать, когда вы измеряете размер чего-либо. Странно, что size_t
требуется только представлять между 0 и SIZE_MAX
байтами, а SIZE_MAX
требуется только 65535...
Другие интересные ограничения из С++ и C:
- возвращаемый тип
sizeof()
равенsize_t
, и это целое число без знака -
operator new()
берет количество байтов для выделения в качестве параметраsize_t
-
size_t
определяется в<cstddef>
-
SIZE_MAX
определяется в<limits.h>
в C99, но не упоминается в С++ 98?! -
size_t
не входит в список основных целых типов, поэтому я всегда предполагал, чтоsize_t
является псевдонимом типа для одного из основных типов:char
,short int
,int
иlong int
.
Если вы подсчитываете байты, то вы обязательно должны использовать size_t
. Если вы подсчитываете количество элементов, то вы, вероятно, должны использовать size_t
, поскольку это похоже на то, что использовал С++. В любом случае вы не хотите использовать int
- по крайней мере, использовать unsigned long
или unsigned long long
, если вы используете TR1. Или... еще лучше... typedef
что бы вы ни использовали в size_type
или просто включили <cstddef>
и использовали std::size_t
.
Ответ 2
Несколько причин могут быть:
- Тип (size_t) может быть определен как наибольшее целое число без знака на этой платформе. Например, он может быть определен как 32-битное целое число или целое число 64 бит или что-то еще, что способно хранить неподписанные значения большой длины
- Чтобы прояснить при чтении программы, что значение является размером, а не просто "регулярным" int
Если вы пишете приложение, которое просто для вас и/или выбрасывание, вы, вероятно, можете использовать базовый int. Если вы пишете библиотеку или что-то существенное, size_t, вероятно, лучший способ пойти.
Ответ 3
Некоторые ответы более сложны, чем необходимо. Size_t - это целочисленный тип без знака, который гарантированно будет достаточно большим, чтобы хранить размер в байтах любого объекта в памяти. На практике он всегда имеет тот же размер, что и тип указателя. В 32-битных системах это 32 бита. В 64-битных системах это 64 бит.
Ответ 4
Все контейнеры в stl имеют различные typedef. Например, value_type
- это тип элемента, а size_type
- тип хранимого числа. Таким образом, контейнеры полностью генерируются на основе платформы и реализации.
Если вы создаете свои собственные контейнеры, вы также должны использовать size_type
. Обычно это делается
typedef std::size_t size_type;
Если вы хотите размер контейнера, вы должны написать
typedef vector<int> ints;
ints v;
v.push_back(4);
ints::size_type s = v.size();
Что хорошего в том, что если позже вы захотите использовать список, просто измените typedef на
typedef list<int> ints;
И он все равно будет работать!
Ответ 5
Я предполагаю, что вы имеете в виду "size_t" - это способ указания целого числа без знака (целое число, которое может быть только положительным, никогда не отрицательным) - оно имеет смысл для размеров контейнеров, поскольку вы не можете иметь массив с размером -7. Я бы не сказал, что вам нужно использовать size_t, но это указывает другим, используя ваш код "Этот номер здесь всегда положительный". Это также дает вам больший диапазон положительных чисел, но это, вероятно, будет несущественным, если у вас нет очень больших контейнеров.
Ответ 6
С++ - это язык, который может быть реализован на разных аппаратных архитектурах и платформах. По прошествии времени он поддерживает 16-, 32- и 64-битную архитектуру и, вероятно, другие в будущем. size_type
и другие псевдонимы типов - это способы для библиотек, чтобы изолировать программистов/код от деталей реализации.
Предполагая, что size_type
использует 32 бита на 32-битных машинах и 64 бита на 64-битных машинах, тот же исходный код, вероятно, будет работать лучше, если вы будете использовать size_type там, где это необходимо. В большинстве случаев вы можете предположить, что он будет таким же, как unsigned int
, но он не гарантируется.
size_type
используется для выражения возможностей контейнеров STL, таких как std::vector
, тогда как size_t
используется для выражения размера байта объекта в C/С++.
Ответ 7
ints не гарантируется в байтах 4 байта, поэтому они не являются надежными. Да, size_type будет предпочтительнее, чем ints
Ответ 8
size_t
не имеет знака, поэтому даже если они оба являются 32 битами, это не означает то же самое, что и неквалифицированный int. Я не уверен, почему они добавили этот тип, но на многих платформах сегодня sizeof (size_t) == sizeof (int) == sizeof (long)
, поэтому тип, который вы выбираете, зависит от вас. Обратите внимание, что эти отношения не гарантируются стандартом и быстро устаревают, когда 64-битные платформы перемещаются.
Для вашего собственного кода, если вам нужно представить что-то, что является "размером" концептуально и никогда не может быть отрицательным, size_t
будет хорошим выбором.
Ответ 9
void f1(size_t n) {
if (n <= myVector.size()) { assert(false); }
size_t n1 = n - myVector.size(); // bug! myVector.size() can be > n
do_stuff_n_times(n1);
}
void f2(int n) {
int n1 = n - static_cast<int>(myVector.size());
assert(n1 >= 0);
do_stuff_n_times(n1);
}
f1() и f2() имеют одинаковый баг, но обнаружение проблемы в f2() проще. Для более сложного кода нечеткие арифметические ошибки без знака не так легко идентифицировать.
Лично я использую подписанный int для всех моих размеров, если не использовать unsigned int. Я никогда не сталкивался с ситуацией, когда мой размер не вписывается в 32-разрядное целое число со знаком. Я, вероятно, буду использовать 64-битные знаковые целые числа, прежде чем использовать 32-битные целые числа без знака.
Проблема с использованием целых чисел со знаком для размера - это много static_cast
от size_t
до int
в вашем коде.