web-dev-qa-db-fra.com

Erreur "Utilisation de la fonction supprimée" avec std :: atomic_int

Je veux utiliser un std::atomic_int variable. Dans mon code, j'ai:

#include <atomic>

std::atomic_int stop = 0;

int main()
{
    // Do something
}

Et cela me donne une erreur de compilation:

use of deleted function 'std::__atomic_base<_IntTp>::__atomic_base(const std::__atomic_base<_IntTp>&) [with _ITp = int]'
 std::atomic_int stop = 0;
                        ^

Une idée de ce qui se passe?

24
Karnivaurus

Votre code tente de construire un std::atomic_int Temporaire sur le RHS, puis utilisez le constructeur de copie std::atomic_int (Qui est deleted) pour initialiser stop, comme ceci :

std::atomic_int stop = std::atomic_int(0);

En effet, copie-initialisation , comme vous le faites ici, n'est pas tout à fait équivalent à d'autres types d'initialisation.

[C++11: 8.5/16]: La sémantique des initialiseurs est la suivante [..]

Si l'initialiseur est une liste d'initiation contreventée (non entre parenthèses), l'objet ou la référence est initialisé par liste ( 8.5.4).

(cela permet l'option 3, à la fin de cette réponse)

[..]

Si le type de destination est un type de classe (éventuellement qualifié cv):

  • Si l'initialisation est initialisation directe , ou si c'est copie-initialisation où la version non qualifiée cv du type source est la même classe ou une classe dérivée de la classe de destination, les constructeurs sont considérés. Les constructeurs applicables sont énumérés (13.3.1.3) , et le meilleur est choisi par la résolution de surcharge (13.3). Le constructeur ainsi sélectionné est appelé pour initialiser l'objet, avec l'expression d'initialisation ou la liste d'expressions comme argument (s). Si aucun constructeur ne s'applique ou si la résolution de surcharge est ambiguë, l'initialisation est incorrecte.

(cela décrit presque votre code mais pas tout à fait; la clé ici est que, peut-être contrairement à l'intuition, les constructeurs de std::atomic_int ne sont pas du tout considérés dans votre cas!)

  • Sinon (c.-à-d. Pour les autres cas copie-initialisation ), séquences de conversion définies par l'utilisateur qui peuvent convertir du type source vers la destination le type ou (lorsqu'une fonction de conversion est utilisée) vers une classe dérivée de celle-ci sont énumérés comme décrit en 13.3.1.4, et le meilleur est choisi par la résolution de surcharge (13.3). Si la conversion ne peut pas être effectuée ou est ambiguë, l'initialisation est mal formé. La fonction sélectionnée est appelée avec l'expression d'initialisation comme argument; si la fonction est un constructeur, l'appel initialise une version temporaire de la version non qualifiée cv du type de destination. Le temporaire est une valeur. Le résultat de l'appel (qui est temporaire pour le cas constructeur) est ensuite utilisé pour initialiser directement , selon les règles ci-dessus , l'objet qui est la destination de la copie-initialisation . Dans certains cas, une implémentation est autorisée pour éliminer la copie inhérente à ceci initialisation directe en construisant le résultat intermédiaire directement dans l'objet en cours d'initialisation; voir 12.2, 12.8.

(c'est votre scénario; donc, bien que la copie puisse être éluée, elle doit toujours être possible)

  • [..]

Voici le correctif, de toute façon; utiliser initialisation directe ou initialisation liste :

std::atomic_int stop(0);     // option 1
std::atomic_int stop{0};     // option 2
std::atomic_int stop = {0};  // option 3
30