size_t vs int предупреждение - PullRequest
43 голосов
/ 05 июля 2011

Я получаю следующее предупреждение всегда для следующего типа кода.

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

Ответы [ 5 ]

48 голосов
/ 05 июля 2011

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

Еще лучше, используйте итераторы:

for( auto it = v.begin(); it != v.end(); ++it )

(Если ваш компилятор не поддерживает C ++ 11, используйте std::vector<whatever>::iterator вместо auto)

C ++ 11 также облегчает выбор лучшего типа индекса (в случае, если вы используете индекс в некоторых вычислениях, а не только для подписки v):

for( decltype(v.size()) i = 0; i < v.size(); ++i )
18 голосов
/ 05 июля 2011

Что такое size_t?
size_t соответствует интегральному типу данных, возвращаемому оператором языка sizeof и определенному в файле заголовка (средидругие) как unsigned integral type.

Можно ли разыграть size_t на int?
Вы можете использовать приведение, если выубедитесь, что размер никогда не будет> 1019 *.

. Если вы пытаетесь написать переносимый код, это не безопасно, потому что

size_t в 64 bit Unix равно 64 bits
size_t в 64 bit Windows равно 32 bits

Так что, если вы перенесете свой код с Unix на Windows и, если выше, это условия, вы будетепотерять данные.

Предложенный ответ

Учитывая оговорку, предлагается сделать i из unsigned integral type или дажелучше использовать его как тип size_t.

11 голосов
/ 05 июля 2011

это безопасно игнорировать это предупреждение, или я должен сделать все мои переменные цикла типа size_t

Нет. Вы открываете себя классу целочисленных атак переполнения. Если размер вектора больше MAX_INT (и у злоумышленника есть способ сделать это), ваш цикл будет работать вечно, вызывая возможность отказа в обслуживании.

Технически, std::vector::size возвращает std::vector::size_type, хотя.

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

5 голосов
/ 21 марта 2013

Вот альтернативное представление от Бьярна Страуструпа: http://www.stroustrup.com/bs_faq2.html#simple-program

for (int i = 0; i<v.size(); ++i) cout << v[i] << '\n';

Да, я знаю, что мог бы объявить i вектором :: size_type, а не просто int для тихих предупреждений изнекоторые гипер-подозрительные компиляторы, но в этом случае я считаю это слишком педантичным и отвлекающим.

Это компромисс.Если вы беспокоитесь, что v.size () может превысить 2 147 483 647, используйте size_t.Если вы используете i в цикле не только для поиска внутри вектора, и вас беспокоят тонкие ошибки со знаком и без знака, используйте int.По моему опыту, последний вопрос является более распространенным, чем первый.Ваш опыт может отличаться.

Также см. Почему size_t без знака? .

5 голосов
/ 05 июля 2011

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

, так как size() возвращает size_t ( не int ), тогда это должен быть тип данных, с которым вы сравниваете его.

std::vector v;
for ( size_t i = 0; i < v.size(); i++) {
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...