2013-07-06 3 views
30

Я получаю предупреждение подписал/без знака рассогласования для следующего кода:Использование авто в шлейфы C++

auto n = a.size(); 
for (auto i = 0; i < n; i++) { 
} 

Проблема заключается в том, что, назначая от 0 до i становится int, а не size_t. Так что лучше:

size_t n = a.size(); 
for (size_t i = 0; i < n; i++) { 
} 

или это:

auto n = a.size(); 
for (size_t i = 0; i < n; i++) { 
} 

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

+3

как насчет 'auto i = 0u'? – jalf

+0

Как насчет использования int, если вам нужен индекс в вашем цикле? Использование индекса без знака может стать очень неприятным. Например. 'i

ответ

38

Диапазона может быть чист раствором:

for (const auto& i : a) 
{ 

} 

Здесь i является const ссылкой на элемент контейнера a.

В противном случае, если вам нужен индекс, или если вы не хотите перебирать весь диапазон, вы можете получить его с помощью decltype(a.size()).

for (decltype(a.size()) i = 0; i < a.size(); ++i) { 
} 
+4

1 проблема с циклом, основанным на диапазонах, заключается в том, что индекс недоступен – RiaD

+0

Да, это большая проблема на самом деле, я не хочу управлять индексами отдельно. – user2381422

+0

Спасибо за это. Я не знал, что C++ 11 представил цикл на основе диапазона. – stepanbujnak

18

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

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

auto n = a.size(); 
for (decltype(n) i = 0; i < n; i++) { 
} 

Таким образом, вы связать i и n типов всегда совпадает друг с другом.

5

Если вы использовали правильный литерал, все будет нормально: 0U. auto видит литерал типа int, так что это тип i. Добавьте U, и вместо этого вы увидите неподписанный int literal. В противном случае вы бы хотели использовать decltype, как предложили другие, тем более, что sizeof (size_t) может быть больше sizeof (int) (он находится в Windows, OS X и т. Д., Если он работает в режиме с 64-разрядным интервалом).

+2

Является ли 'sizeof (0U)' always' sizeof (size_t) 'стандартным? – Flexo

+0

@Flexo: Сообщение отредактировано, чтобы отразить это, и поощрять принятие другого ответа. –

+0

-1. Первая половина этого ответа неверна, как говорит Флексо. А вторая половина в основном говорит: «Делайте, как говорят другие ответы». Если вы хотите «поощрять принятие другого ответа», вы можете удалить его. – interjay

-2
for(auto n = a.size(), i = 0; i != n; ++i) { 
} 

... возможно, самое чистое решение, если вам нужно получить доступ к индексу, а также к фактическому элементу.

Update:

for(auto n = a.size(), i = n*0; i != n; ++i) { 
} 

Было бы обходной путь для Richard Smiths комментарий, хотя это не выглядит, что чистый больше.

+4

Это неверно: в декларации 'auto', которая объявляет несколько переменных,' auto' выводится независимо для каждой переменной, а код плохо сформирован, если выведенные типы не совпадают. –

2

Для обсуждения:

auto n = a.size(); 
for (auto i = n-n; i<n; ++i) { 
} 

Обратите внимание, что для типов меньше int, результат вычитания расширяется до int (так называемого целочисленного продвижения).

1

Попытки быть константным-правильно, когда это возможно, я обычно пишу:

const auto n(a.size()); 
for (auto i = decltype(n){0}; i < n; ++i) 
{ 
} 

Это не очень краткое, но это понятно, что вы хотите переменный инициализируются 0 типа n «s (и nconst).

0

Вот простое решение для очистки &, чтобы оно работало.

for(auto i: a) 
{ 
} 
Смежные вопросы