Если я использую станд.:: size_t или интервал в моем для циклов?

Я просто задаюсь вопросом, должен я использовать std::size_t для циклов и материала вместо int? Например:

#include <cstdint>

int main()
{
    for (std::size_t i = 0; i < 10; ++i) {
        // std::size_t OK here? Or should I use, say, unsigned int instead?
    }
}

В целом, что расценивает лучшая практика, когда использовать std::size_t?

187
задан Pharap 20 August 2019 в 09:30
поделиться

9 ответов

Хорошее эмпирическое правило для всего, что нужно сравнить в условии цикла с чем-то, что само по себе является std::size_t.

std::size_t - это тип любого выражения sizeof и как гарантированно может выразить максимальный размер любого объекта (включая любой массив) на языке Си++. Дополнительно гарантируется, что он будет достаточно большим для любого индекса массива, поэтому он является естественным типом для цикла по индексу над массивом.

Если вы просто считаете до числа, то более естественным может быть использование либо типа переменной, содержащей это число, либо int или unsigned int (если они достаточно большие), так как они должны быть естественным размером для машины.

.
172
ответ дан 23 November 2019 в 05:46
поделиться

size_t is unsigned int, поэтому везде, где нужно использовать unsigned int, можно использовать его.

Я использую его, когда хочу задать размер массива, счетчик и т.д...

void * operator new (size_t size); is a good use of it.
-4
ответ дан 23 November 2019 в 05:46
поделиться

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

Некоторые функции возвращают size_t, и ваш компилятор предупредит вас, если вы попытаетесь провести сравнение.

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

-3
ответ дан 23 November 2019 в 05:46
поделиться

size_t является беззнаковым типом, который может содержать максимальное целое значение для вашей архитектуры, поэтому он защищен от целочисленных переполнений из-за знакового (знаковый int 0x7FFFFFFFF, увеличенный на 1, даст -1) или короткого размера (беззнаковый короткий int 0xFFFFFF, увеличенный на 1, даст 0).

В основном он используется в индексировании массивов/петлях/адресной арифметике и так далее. Функции типа memset() и так принимают только size_t, так как теоретически возможен блок памяти размером 2^32-1 (на 32-битной платформе).

Для таких простых циклов не надо беспокоиться и используйте только int.

.
-1
ответ дан 23 November 2019 в 05:46
поделиться

По определению, size_t является результатом оператора sizeof. size_t был создан для обращения к размерам.

Количество раз, когда вы что-то делаете (10, в вашем примере), не имеет отношения к размерам, так зачем использовать size_t? int, или unsigned int, должно быть нормально.

Конечно, это также относится и к тому, что вы делаете с i внутри цикла. Если вы передаете его в функцию, которая принимает unsigned int, например, pick unsigned int.

В любом случае, я рекомендую избегать неявных приведений типов. Сделать явными все приведения типов.

12
ответ дан 23 November 2019 в 05:46
поделиться

Тип size_t предназначен для указания размера size чего-либо, поэтому естественно использовать его, например, получать длину строки, а затем обрабатывать каждый символ:

for (size_t i = 0, max = strlen (str); i < max; i++)
    doSomethingWith (str[i]);

Вы do, конечно же, должны следить за граничными условиями, так как это беззнаковый тип. Граница на верхнем конце обычно не так важна, так как максимум обычно большой (хотя туда можно добраться -). Большинство людей просто используют для этого int, так как редко имеют структуры или массивы, которые становятся достаточно большими, чтобы превысить емкость этого int.

Но обратите внимание на такие вещи, как:

for (size_t i = strlen (str) - 1; i >= 0; i--)

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

for (size_t i = strlen (str); i-- > 0; )

Путем сдвига декремента в сторону побочного эффекта после проверки условия продолжения, это делает проверку продолжения на значение до декремента, но всё равно использует декрементированное значение внутри цикла (поэтому цикл выполняется от len ... 1, а не от len-1 ... 0).

.
31
ответ дан 23 November 2019 в 05:46
поделиться

Для индексации/счета массивов в стиле C используйте std::size_t.

Для контейнеров STL у вас будет (например) vector::size_type, который должен использоваться для индексации и подсчета векторных элементов.

На практике, как правило, они оба являются беззнаковыми ints, но это не гарантируется, особенно при использовании пользовательских аллокаторов.

.
8
ответ дан 23 November 2019 в 05:46
поделиться

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

10
ответ дан 23 November 2019 в 05:46
поделиться

size_t - тип результата оператора sizeof.

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

Также использование size_t для представления размера в байтах помогает сделать код портативным.

.
70
ответ дан 23 November 2019 в 05:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: