Почему конструктор std :: atomic ведет себя по-разному в C ++ 14 и C ++ 17

19

Я работаю в проекте с C ++ 11, и я попробовал следующий код

#include <atomic>

struct A {
    std::atomic_int idx = 1;

};

int main() {
    return 0;
}

Я получаю ошибку компилятора

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

Тот же результат с C ++ 14. Когда я переключаюсь на C ++ 17, это работает: wandbox

Я проверил cppreference на различия:

Но нет никакой разницы, документированной между C ++ 14 и C ++ 17. Почему он работает с C ++ 17, а не с C ++ 14?

Томас Саблик
источник
Какой компилятор / стандартная библиотека / платформа вы используете?
Виктор Губин
@VictorGubin Я попробовал с Clang и GCC на Linux (Wandbox). Я пробовал разные версии.
Томас
1
Вы можете упростить MCVE до локального main(или любой другой функции, которая не требуется main) вместо конструктора структуры. Clang выдает похожее сообщение об ошибке, будучи более явным, что он пытается использовать конструктор удаленной копии вместо инициализатора или простого конструктора: godbolt.org/z/SBGf9w с libc ++
Питер Кордес
@PeterCordes Я не был уверен, связана ли эта ошибка с инициализацией класса.
Томас
3
Получение того же сообщения об ошибке для более простого минимального воспроизводимого примера доказывает, что это не так. Я тоже не был уверен, пока не попробовал.
Питер Кордес

Ответы:

29

Потому что в C ++ 17 есть гарантированный RVO. В C ++ 14 операторы похожи Foo x = Foo(args)и Foo x (args)технически не совпадают, но они есть в 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(); 
}

Вы можете прочитать больше об этом здесь: https://en.cppreference.com/w/cpp/language/copy_elision

В частности раздел (since C++17):

T x = T (T (f ())); // только один вызов конструктора по умолчанию для T, чтобы инициализировать x

Чтобы заставить работать код C ++ 14, вы можете использовать

std::atomic_int idx { 1 };
Ринат Велиахмедов
источник