size_t против int в C ++ и / или C - PullRequest
29 голосов
/ 15 июня 2009

Почему в контейнерах C ++ возвращается size_type, а не int? Если мы создаем наши собственные структуры, следует ли нам также рекомендовать использовать size_type?

Ответы [ 9 ]

26 голосов
/ 15 июня 2009

Как правило, size_t следует использовать всякий раз, когда вы измеряете размер чего-либо. Действительно странно, что size_t требуется только для представления от 0 до SIZE_MAX байтов, а SIZE_MAX - только 65 535 ...

Другие интересные ограничения из стандартов C ++ и C:

  • тип возврата sizeof() равен size_t, и это целое число без знака
  • operator new() принимает количество байтов для выделения в качестве size_t параметра
  • size_t определено в <cstddef>
  • SIZE_MAX определяется в <limits.h> в C99, но не упоминается в C ++ 98?!
  • size_t не включен в список фундаментальных целочисленных типов , поэтому я всегда предполагал, что size_t является псевдонимом типа для одного из фундаментальных типов: char, short int, int и long int.

Если вы считаете байты, то вам определенно следует использовать size_t. Если вы подсчитываете количество элементов, то вам, вероятно, следует использовать size_t, поскольку это, похоже, то, что использовал C ++. В любом случае, вы не хотите использовать int - по крайней мере, использовать unsigned long или unsigned long long, если вы используете TR1. Или ... еще лучше ... typedef что бы вы ни использовали в size_type или просто включите <cstddef> и используйте std::size_t.

9 голосов
/ 15 июня 2009

Причин может быть несколько:

  • Тип (size_t) можно определить как наибольшее целое число без знака на этой платформе. Например, он может быть определен как 32-разрядное целое или 64-разрядное целое число или что-то еще, что может хранить беззнаковые значения большой длины
  • Чтобы при чтении программы было понятно, что значение является размером, а не просто "обычным" int

Если вы пишете приложение, которое предназначено только для вас и / или одноразового использования, вы, вероятно, можете использовать базовый int. Если вы пишете библиотеку или что-то существенное, вероятно, лучше использовать size_t.

5 голосов
/ 18 июня 2009

Некоторые ответы сложнее, чем необходимо. Size_t - это целочисленный тип без знака, который гарантированно будет достаточно большим для хранения размера в байтах любого объекта в памяти На практике это всегда тот же размер, что и тип указателя. На 32-битных системах это 32-битные. На 64-битных системах это 64-битные.

2 голосов
/ 15 июня 2009

Все контейнеры в stl имеют различные определения типов. Например, 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;

И все равно будет работать!

1 голос
/ 15 июня 2009

C ++ - это язык, который может быть реализован на разных аппаратных архитектурах и платформах. Со временем он поддерживал 16-, 32- и 64-битную архитектуру и, вероятно, другие в будущем. size_type и псевдонимы других типов позволяют библиотекам изолировать программистов / код от деталей реализации.

Предполагая, что size_type использует 32 бита на 32-битных машинах и 64 бита на 64-битных машинах, тот же исходный код, вероятно, будет работать лучше, если вы используете size_type там, где это необходимо. В большинстве случаев можно предположить, что это будет то же самое, что и unsigned int, но это не гарантируется.

size_type используется для выражения емкости контейнеров STL, таких как std::vector, тогда как size_t используется для выражения размера объекта в байтах в C / C ++.

1 голос
/ 15 июня 2009

Я предполагаю, что вы имеете в виду «size_t» - это способ указать целое число без знака (целое число, которое может быть только положительным, но не отрицательным) - это имеет смысл для размеров контейнеров, так как вы не можете иметь массив с размером -7. Я бы не сказал, что вы должны использовать size_t, но он указывает другим, кто использует ваш код: «Это число всегда положительно». Это также дает вам больший диапазон положительных чисел, но это, вероятно, будет неважно, если у вас нет очень больших контейнеров.

0 голосов
/ 15 июня 2009

size_t не имеет знака, поэтому даже если они оба 32-разрядные, это не означает, что это не то же самое, что и для неквалифицированного целого. Я не уверен, почему они добавили тип, но на многих платформах сегодня sizeof (size_t) == sizeof (int) == sizeof (long), так что какой тип вы выбираете, зависит от вас. Обратите внимание, что эти отношения не гарантируются стандартом и быстро устаревают по мере продвижения 64-битных платформ.

Для вашего собственного кода, если вам нужно концептуально представить что-то, что является «размером» и никогда не может быть отрицательным, size_t будет хорошим выбором.

0 голосов
/ 15 июня 2009
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 в вашем коде.

0 голосов
/ 15 июня 2009
Не гарантируется, что

ints будут 4 байта в спецификации, поэтому они не являются надежными. Да, size_type предпочтительнее, чем целые числа

...