Warum verhält sich der std :: atomic-Konstruktor in C ++ 14 und C ++ 17 anders?

19

Ich arbeite in einem Projekt mit C ++ 11 und habe versucht, folgenden Code zu verwenden

#include <atomic>

struct A {
    std::atomic_int idx = 1;

};

int main() {
    return 0;
}

Ich bekomme den Compilerfehler

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

Das gleiche Ergebnis ist mit C ++ 14. Wenn ich zu C ++ 17 wechsle, funktioniert es: wandbox

Ich habe cppreference auf Unterschiede überprüft:

Es ist jedoch kein Unterschied zwischen C ++ 14 und C ++ 17 dokumentiert. Warum funktioniert es mit C ++ 17 und nicht mit C ++ 14?

Thomas Sablik
quelle
Welche Compiler / Standardbibliothek / Plattform verwenden Sie?
Victor Gubin
@ VictorGubin Ich habe es mit Clang und GCC unter Linux (Wandbox) versucht. Ich habe verschiedene Versionen ausprobiert.
Thomas Sablik
1
Sie können die MCVE anstelle eines Strukturkonstruktors auf ein lokales In main(oder eine beliebige Funktion, die nicht erforderlich ist) vereinfachen main. Clang gibt eine ähnliche Fehlermeldung aus, da expliziter versucht wird, einen gelöschten Kopierkonstruktor anstelle des Initialisierers oder einfachen Konstruktors zu verwenden: godbolt.org/z/SBGf9w mit libc ++
Peter Cordes
@PeterCordes Ich war mir nicht sicher, ob dieser Fehler mit der Klasseninitialisierung zusammenhängt.
Thomas Sablik
3
Die gleiche Fehlermeldung für ein einfacheres, minimal reproduzierbares Beispiel zu erhalten, beweist, dass dies nicht der Fall ist. Ich war mir auch nicht sicher, bis ich es versuchte.
Peter Cordes

Antworten:

29

Denn in C ++ 17 gibt es eine garantierte RVO. In C ++ 14 mögen Foo x = Foo(args)und Foo x (args)sind Anweisungen technisch nicht gleich, aber sie sind in C ++ 17.

struct Foo {
    Foo() = default;
    Foo(const Foo&) = delete;
};

int main() {
    // Works in C++17 and C++20, fails in C++14 and before
    Foo foo = Foo(); 
}

Weitere Informationen hierzu finden Sie hier: https://en.cppreference.com/w/cpp/language/copy_elision

Insbesondere der Abschnitt (since C++17):

T x = T (T (f ())); // nur ein Aufruf des Standardkonstruktors von T, um x zu initialisieren

Damit C ++ 14-Code funktioniert, können Sie verwenden

std::atomic_int idx { 1 };
Rinat Veliakhmedov
quelle