2015-02-02 2 views
1

Я хочу избежать предупреждений о сравнении между unsigned int и подписанным int.Есть ли более элегантный способ сделать следующее в C++ 11?

Я использую петли, такие как:

for (int i =0 ; i < vec.size(); i++) { 
// do something 
} 

, который дает эти предупреждения (что само по себе хорошо, я хочу, высокий уровень предупреждений).

Я думал об изменении его на следующее:

for (auto i = vec.size()*0; i < vec.size(); i++) { 
// do something 
} 

в этом случае я не получаю предупреждения. Но мне интересно, есть ли что-то более элегантное, чем это, что автоматически выводит тип, необходимый для итератора.

+6

Используйте конструкцию 'range for'. 'for (auto const & v: vec) {}'. –

+1

'decltype' позволит вам автоматически выводить тип на основе значения. –

+1

Существует 'for (decltype (vec.size()) i = 0; i

ответ

8

Использование диапазона на основе цикл

for (auto& i : vec) 
{ 
    cout << *i; 
} 

использовать итераторы.

for (auto it = vec.begin(), end_it = vec.end(); it != end_it; ++it) 
{ 
    cout << *it; 
} 

Если вы хотите счетчик, используйте std::vector<T>::size_type или просто size_t, если вы ленивы.

+2

Я бы не сказал, что использование 'size_t' является ленивым. Единственный раз, когда вы действительно хотите использовать 'size_type', является универсальное программирование, когда контейнер является типом шаблона. В остальное время вы знаете, что 'size_type' является' size_t', но 'size_t' намного чище писать. – David

+0

'end_it = vec.end()' довольно ненужная преждевременная оптимизация IMO, и я вообще не против, кроме случаев, когда это ухудшает простоту/удобочитаемость кода. – David

+0

Это привычка, привычка, к которой я привык, и я намерен сохранить :) –

-1

Поскольку вопрос начинается с фразой:

«Я хочу, чтобы избежать предупреждений о сравнении между неподписанными INT и подписанных междами»

Я предположил, что vec.size() возвращает unsigned int.

Если тип, возвращаемый vec.size(), может быть сохранен в unsigned int, то вы можете использовать следующее.

for (auto i = 0u; i < vec.size(); i++) { 
     // do something 
} 

В противном случае используйте соответствующий тип или проверьте другие ответы.

Если vec имеет тип std::vector<T> (который не был упомянут в вопросе, следовательно, выше коде) вы можете также использовать цикл for_each (который также не был упомянут)

std::for_each(vec.begin(), vec.end(), [](T t){ /* do something with t */ }); 
std::for_each(vec.begin(), vec.end(), [](T & t){ /* do something with t */}); 
std::for_each(vec.begin(), vec.end(), [](const T & t){ /* do something with t */ }); 

Это может быть более удобно, если у вас есть ходить по векторным элементам с некоторыми уже существующими функциональными-объектами (или методы или функцию, не являющиеся членами)

void f(int x) { std::cout << "f: " << x << "\n"; } 
void g(int x) { std::cout << "g: " << x << "\n"; } 
... 
std::vector<int> vec{1, 2, 3}; 
std::for_each(vec.begin(), vec.end(), std::bind(f, std::placeholders::_1)); //calls f(int) 
std::for_each(vec.begin(), vec.end(), std::bind(g, std::placeholders::_1)); //calls g(int) 

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

std::function<void(int)> callback = std::bind(f, std::placeholders::_1); 
if (userWantsG()) 
    callback = std::bind(g, std::placeholders::_1); 
std::for_each(vec.begin(), vec.end(), callback); //calls g or f 
+2

Это будет ужасно неправильно, если размер слишком велик для 'unsigned int'. –

+0

@MikeSeymour вопрос не говорит, что возвращается 'vec.size()'. Он только спрашивает, как избежать предупреждений о сравнении между unsigned int и подписанным int. – doc

+0

Разумно предположить, что 'vec.size()' является 'std :: vector :: size' –

0

Или даже петли по убыванию:

auto i = vec.size(); 
while (i --> 0) 
    // ... 
+2

как насчет 'for (auto i = vec.size(); i -> 0;)' Ничто не похоже на использование '->', чтобы люди, относительно новые для C++, говорили «wtf?». Также большинство людей собирается сказать, что это ужасно, не делайте этого. – David

+0

@Dave работает одинаково, но я бы предпочел бы 'while', потому что вы сказали бы« в то время как x идет к нулю ». – edmz

+0

Ну, вы можете написать любой цикл для цикла while. Вы никогда не пишете для петель? В этом случае вы можете написать любой цикл while с goto. Это все синтаксический сахар. Я пишу это, но я согласен с вами, «пока» является единственным, который правильно читается на английском языке. – David

1

Если это вариант, предпочитают стандартной библиотеки примитивов высшего порядка из <algorithm>, такие как (не ограничиваясь ими):

  • std::accumulate
  • std::copy
  • std::transform

Они очень выразительны при использовании с лямбдами. Используйте только for, если это не вариант, и предпочитайте цикл for-for.

Смежные вопросы