Предупреждение size_t против int
Я всегда предупреждаю о следующем типе кода.
std::vector v;
for ( int i = 0; i < v.size(); i++) {
}
warning C4267: 'initializing' : conversion from 'size_t' to 'int', possible loss of data
Я понимаю, что size()
возвращает size_t
, просто хотел знать, насколько безопасно игнорировать это предупреждение или я должен сделать всю свою переменную цикла типа size_t
Ответы
Ответ 1
Если вам может потребоваться удерживать больше элементов INT_MAX
в вашем векторе, используйте size_t
. В большинстве случаев это не имеет особого значения, но я использую size_t
только для предупреждения.
Еще лучше, используйте итераторы:
for( auto it = v.begin(); it != v.end(); ++it )
(Если ваш компилятор не поддерживает С++ 11, используйте std::vector<whatever>::iterator
вместо auto
)
С++ 11 также упрощает выбор наилучшего типа индекса (в случае, если вы используете индекс в некоторых вычислениях, а не только для подписи v
):
for( decltype(v.size()) i = 0; i < v.size(); ++i )
Ответ 2
Что такое size_t
?
size_t
соответствует интегральному типу данных, возвращаемому оператором языка sizeof
и определяется в файле заголовка (среди прочих) как unsigned integral type
.
Можно ли отбрасывать size_t
до int
?
Вы можете использовать бросок, если вы уверены, что размер никогда не будет > чем INT_MAX
.
Если вы пытаетесь написать переносимый код, он безопасен не, потому что
size_t
в 64 bit Unix
есть 64 bits
size_t
в 64 bit Windows
есть 32 bits
Итак, если вы портируете код из Unix в WIndows, а если выше, то вы потеряете данные.
Рекомендуемый ответ
Учитывая оговорку, нужно сделать i
of unsigned integral type
или даже лучше использовать его как тип size_t
.
Ответ 3
безопасно ли игнорировать это предупреждение или я должен сделать всю свою переменную цикла типа size_t
Нет. Вы открываете себя до класса целых атак переполнения. Если размер вектора больше, чем MAX_INT
(и у злоумышленника есть способ сделать это), ваш цикл будет работать вечно, что вызовет отказ в обслуживании.
Технически, std::vector::size
возвращает std::vector::size_type
.
Вы должны использовать правильную подпись для переменных счетчика циклов. (Действительно, для большинства применений вы хотите, чтобы целые числа без знака, а не целые числа со знаком для циклов)
Ответ 4
Проблема заключается в том, что вы смешиваете два разных типа данных. На некоторых архитектурах size_t
представляет собой 32-разрядное целое число, а на других - 64-битное. Ваш код должен правильно обрабатывать оба.
поскольку size()
возвращает a size_t
(not int), тогда это должен быть тип данных, с которым вы сравниваете его.
std::vector v;
for ( size_t i = 0; i < v.size(); i++) {
}
Ответ 5
Здесь альтернативный вид Бьярне Страуструпа:
http://www.stroustrup.com/bs_faq2.html#simple-program
for (int i = 0; i<v.size(); ++i) cout << v[i] << '\n';
Да, я знаю, что могу объявить, что я должен быть vector:: size_type а не простой int для спокойных предупреждений от некоторых подозрительных компиляторов, но в этом случае я считаю, что слишком педантичный и отвлекает внимание.
Это компромисс. Если вы обеспокоены тем, что v.size() может пройти выше 2,147,483,647, используйте size_t. Если вы используете я внутри своего цикла больше, чем просто смотрите внутри вектора, и вас беспокоят тонкие связанные или неподписанные ошибки, используйте int. По моему опыту, последний вопрос более распространен, чем первый. Ваш опыт может отличаться.
Также см. Почему size_t unsigned?.