Подтвердить что ты не робот

Size_t vs int в С++ и/или C

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

4b9b3361

Ответ 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 в вашем коде.