2013-06-10 2 views
40

В C++ 11, я могу перебрать некоторый контейнер таким образом:C++ 11 Range основы для цикла эффективность «Const авто и я» против «авто я»

for(auto i : vec){ 
    std::cout << i << std::endl; 
} 

Но я знаю, что это излишне - понапрасну, так как мне нужно только печати значения vec - делает копию (EDIT: каждый элемент) vec, поэтому вместо того, чтобы я мог сделать:

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

Но я хочу, чтобы убедиться, что значения vec никогда не изменяются и соблюдать сопзЬ корректности, так что я могу сделать:

for(const auto &i : vec){ 
    std::cout << i << std::endl; 
} 

Так что мой вопрос: если мне нужно только взгляд в то значения какого-либо контейнера, не всегда был бы самый последний цикл (const auto &i) из-за повышенной эффективности отсутствия дополнительной копии (EDIT: каждый элемент) vec?

У меня есть программа, которую я разрабатываю, в которой я планирую сделать это изменение повсюду, поскольку эффективность в нем важна (причина, по которой я использую C++ в первом месте).

+1

Да, если вам нужен только доступ для чтения к аргументу, это должно быть через 'auto const &', чтобы избежать ненужной копии. – 0x499602D2

+2

Ключевое слово «const» не делает ваш код более быстрым, хотя ... – Tim

+4

'for (auto i: vec)' не делает дополнительной копии всего 'vec', он копирует каждый _element_' vec' в 'i'. – Casey

ответ

54

Да. По той же причине, если вы только когда-либо читали аргумент, вы делаете параметр const&.

T  // I'm copying this 
T&  // I'm modifying this 
const T& // I'm reading this 

Это ваши «значения по умолчанию». Когда T является фундаментальным типом (встроенным), вы обычно просто возвращаетесь к const T (без ссылки) для чтения, потому что копия дешевле, чем наложение.


У меня есть программа, что я развивающуюся, в котором я рассматриваю делает это изменение во всем, так как эффективность имеет решающее значение в этом

  1. Не делать слепыми радикальные изменения , Рабочая программа лучше быстрой, но сломанной программы.
  2. Как вы повторяете свои петли, вероятно, не будет иметь большого значения; вы зацикливаетесь по какой-то причине, не так ли? Тело вашей петли, скорее всего, станет виновником.
  3. Если эффективность имеет решающее значение, вы хотите использовать профилировщик, чтобы выяснить, какие части вашей программы являются на самом деле медленно, а не угадывать части, которые могли бы быть медленными. См. № 2, почему ваша догадка может быть неправильной.
+0

«копия дешевле, чем наложение», только с большинством фундаментальных типов, кроме того, семантика перемещения не может использоваться в ситуации OP, и поскольку T может быть любым типом, эта ссылка будет правильным выбором. – Tim

+1

«*» копия дешевле, чем наложение псевдонимов «только с большинством фундаментальных типов». Поэтому первая половина этого предложения посвящена утверждению, что оно относится к фундаментальным типам ...? Очевидно, если вы не знаете тип, вы используете общий случай. – GManNickG

+0

Простите, я, должно быть, прочитал. – Tim

0

Представьте, если ваш вектор содержит строки. Длинные струны. 5000 длинных струн. Скопируйте их без необходимости, и вы получите красиво написанный цикл, который ужасно неэффективен.

Убедитесь, что ваш код соответствует вашим намерениям. Если вам не нужна копия внутри цикла, не делайте ее.

Используйте ссылку &, как предложено выше, или итераторы.

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