Recherche…


Remarques

Le mot clé auto est un nom de fichier représentant un type déduit automatiquement.

C'était déjà un mot-clé réservé en C ++ 98, hérité de C. Dans les anciennes versions de C ++, il pouvait être utilisé pour indiquer explicitement qu'une variable a une durée de stockage automatique:

int main()
{
  auto int i = 5; // removing auto has no effect
}

Cette ancienne signification est maintenant supprimée.

Échantillon automatique de base

Le mot auto clé auto fournit la déduction automatique du type d'une variable.

C'est particulièrement pratique pour traiter les noms de type long:

std::map< std::string, std::shared_ptr< Widget > > table;
// C++98
std::map< std::string, std::shared_ptr< Widget > >::iterator i = table.find( "42" );
// C++11/14/17
auto j = table.find( "42" );

avec des boucles basées sur la plage :

vector<int> v = {0, 1, 2, 3, 4, 5};
for(auto n: v)
    std::cout << n << ' ';

avec lambdas :

auto f = [](){ std::cout << "lambda\n"; };
f();        

pour éviter la répétition du type:

auto w = std::make_shared< Widget >();

pour éviter des copies surprenantes et inutiles:

auto myMap = std::map<int,float>();
myMap.emplace(1,3.14);

std::pair<int,float> const& firstPair2 = *myMap.begin();  // copy!
auto const& firstPair = *myMap.begin();  // no copy!

La raison de la copie est que le type renvoyé est en fait std::pair<const int,float> !

auto et modèles d'expression

auto peut également causer des problèmes lorsque des modèles d'expression entrent en jeu:

auto mult(int c) {
    return c * std::valarray<int>{1};
}

auto v = mult(3);
std::cout << v[0]; // some value that could be, but almost certainly is not, 3.

La raison en est que l' operator* sur valarray vous donne un objet proxy qui fait référence à la valarray comme moyen d'évaluation valarray . En utilisant auto , vous créez une référence en suspens. Au lieu de mult avait renvoyé un std::valarray<int> , alors le code imprimerait définitivement 3.

auto, const et références

Le mot auto clé auto représente lui-même un type de valeur, similaire à int ou char . Il peut être modifié avec le mot-clé const et le symbole & pour représenter respectivement un type const ou un type de référence. Ces modificateurs peuvent être combinés.

Dans cet exemple, s est un type de valeur (son type sera infd std::string ), donc chaque itération de la boucle for copie une chaîne du vecteur dans s .

std::vector<std::string> strings = { "stuff", "things", "misc" };
for(auto s : strings) {
    std::cout << s << std::endl;
}

Si le corps de la boucle modifie s (comme en appelant s.append(" and stuff") ), seule cette copie sera modifiée, pas le membre d'origine des strings .

Par contre, si s est déclaré avec auto& ce sera un type de référence (supposé être std::string& ), donc à chaque itération de la boucle, une référence à une chaîne dans le vecteur lui sera attribuée:

for(auto& s : strings) {
    std::cout << s << std::endl;
}

Dans le corps de cette boucle, les modifications apportées à s affecteront directement l'élément des strings auquel il fait référence.

Enfin, si s est déclaré const auto& , il s'agira d'un type de référence const, ce qui signifie qu'à chaque itération de la boucle, une référence const sera affectée à une chaîne dans le vecteur:

for(const auto& s : strings) {
    std::cout << s << std::endl;
}

Dans le corps de cette boucle, les s ne peuvent pas être modifiés (c.-à-d. Qu'aucune méthode non-const ne peut y être appelée).

Lorsque vous utilisez auto avec for boucles basées for plages, il est généralement recommandé d'utiliser const auto& si le corps de la boucle ne modifie pas la structure en boucle, car cela évite les copies inutiles.

Type de retour

auto est utilisé dans la syntaxe pour le type de retour de fin:

auto main() -> int {}

ce qui équivaut à

int main() {}

Principalement utile combiné avec decltype pour utiliser des paramètres au lieu de std::declval<T> :

template <typename T1, typename T2>
auto Add(const T1& lhs, const T2& rhs) -> decltype(lhs + rhs) { return lhs + rhs; }

Lambda générique (C ++ 14)

C ++ 14

C ++ 14 permet d'utiliser auto dans l'argument lambda

auto print = [](const auto& arg) { std::cout << arg << std::endl; };

print(42);
print("hello world");

Ce lambda est essentiellement équivalent à

struct lambda {
    template <typename T>
    auto operator ()(const T& arg) const {
        std::cout << arg << std::endl;
    }
};

et alors

lambda print;

print(42);
print("hello world");

objets auto et proxy

Parfois, l' auto peut ne pas se comporter comme prévu par un programmeur. Il en déduit l'expression, même si la déduction de type n'est pas la bonne chose à faire.

Par exemple, lorsque des objets proxy sont utilisés dans le code:

std::vector<bool> flags{true, true, false};
auto flag = flags[0];
flags.push_back(true);

Ici, flag ne serait pas bool , mais std::vector<bool>::reference , car pour la spécialisation bool du template vector l' operator [] renvoie un objet proxy avec l'opérateur d' operator bool conversion operator bool défini.

Lorsque flags.push_back(true) modifie le conteneur, cette pseudo-référence peut se terminer par un élément qui n'existe plus.

Cela rend également la prochaine situation possible:

void foo(bool b);

std::vector<bool> getFlags();

auto flag = getFlags()[5];
foo(flag);

Le vector est éliminé immédiatement, donc flag est une pseudo-référence à un élément qui a été supprimé. L'appel à foo invoque un comportement indéfini.

Dans des cas comme celui-ci, vous pouvez déclarer une variable avec auto et l'initialiser en la convertissant au type que vous voulez déduire:

auto flag = static_cast<bool>(getFlags()[5]);

mais à ce stade, remplacer simplement auto par bool plus de sens.

Un autre cas où des objets proxy peuvent causer des problèmes est celui des modèles d'expression . Dans ce cas, les modèles ne sont parfois pas conçus pour durer au-delà de la pleine expression complète pour des raisons d'efficacité, et l'utilisation de l'objet proxy sur le prochain entraîne un comportement indéfini.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow