Lendo alguns exemplos de loops baseados em intervalo, eles sugerem duas maneiras principais 1 , 2 , 3 , 4
std::vector<MyClass> vec;
for (auto &x : vec)
{
// x is a reference to an item of vec
// We can change vec's items by changing x
}
ou
for (auto x : vec)
{
// Value of x is copied from an item of vec
// We can not change vec's items by changing x
}
Bem.
Quando não precisamos alterar vec
itens, os Exemplos da IMO sugerem o uso da segunda versão (por valor). Por que eles não sugerem algo que const
faça referência (pelo menos eu não encontrei nenhuma sugestão direta):
for (auto const &x : vec) // <-- see const keyword
{
// x is a reference to an const item of vec
// We can not change vec's items by changing x
}
Não é melhor? Não evita uma cópia redundante em cada iteração enquanto é const
?
const auto &x
é equivalente à sua terceira escolha.auto&&
quando você não deseja fazer uma cópia desnecessária e não se importa se a modifica ou não, e deseja apenas trabalhar.const
com certeza. No entanto, se seriaauto const &
, ouauto const
tem pouca diferença. Eu escolheriaauto const &
apenas ser mais consistente.Se você tem um
std::vector<int>
oustd::vector<double>
, é bom usarauto
(com cópia de valor) em vez deconst auto&
, pois copiar umint
ou adouble
é barato:Mas se você tiver um
std::vector<MyClass>
, ondeMyClass
tenha alguma semântica de cópia não trivial (por exemplostd::string
, alguma classe personalizada complexa etc.), sugiro usarconst auto&
para evitar cópias profundas :fonte
Então eles dão uma sugestão errada.
Porque eles dão uma sugestão errada :-) O que você mencionou está correto. Se você deseja apenas observar um objeto, não há necessidade de criar uma cópia e não há uma
const
referência a ele.EDITAR:
Vejo que as referências que você vincula fornecem exemplos de iterações sobre um intervalo de
int
valores ou algum outro tipo de dados fundamental. Nesse caso, uma vez que copiar umint
não é caro, criar uma cópia é basicamente equivalente a (se não for mais eficiente do que) ter uma observaçãoconst &
.No entanto, esse não é o caso em geral para tipos definidos pelo usuário. UDTs pode ser caro para copiar e, se você não tiver um motivo para criar uma cópia (como modificar o objeto recuperado sem alterar o original), é preferível usar a
const &
.fonte
Vou ser contrário aqui e dizer que não há necessidade de
auto const &
um intervalo baseado em loop. Diga-me se você acha que a seguinte função é boba (não em seu propósito, mas na maneira como está escrita):Aqui, o autor criou uma referência const
v
para usar em todas as operações que não modificam v. Isso é bobagem, na minha opinião, e o mesmo argumento pode ser usado para usarauto const &
como variável em um intervalo baseado em loop em vez de apenasauto &
.fonte
const_iterator
em um loop for? Como garantir que você não altere os itens originais de um contêiner ao iterá-lo?const_iterator
? Deixe-me adivinhar, o contêiner sobre o qual você interage éconst
. Mas por que éconst
para começar? Em algum lugar que você está usandoconst
para garantir o que?const
é como as vantagens de usarprivate
/protected
nas classes. Evita mais erros.v
, a implementação seria boa para a IMO. E se o loop nunca modifica os objetos pelos quais itera, parece-me correto fazer uma refconst
. Entendo seu ponto de vista. O meu é que o loop representa uma unidade de código da mesma forma que a função e, dentro dessa unidade, não há instruções que precisem modificar o valor. Portanto, você pode "marcar" a unidade inteira comoconst
, como faria com umaconst
função de membro.const &
que o baseado em intervalo é tolo, porque você escreveu um exemplo imaginário irrelevante de um programador imaginário que fez algo tolo com a qualificação cv ? ... OK então