Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does std::atomic compile from C++17 even with a deleted copy constructor?

I have a simple code:

#include <atomic>

int main()
{
    std::atomic<int> a = 0;
}

This code compiles fine with GCC 11.1.0 with -std=c++17, but fails with -std=c++14 and -std=c++11.

using a deleted function std::atomic::atomic(const std::atomic&)

Why is that? In C++17 class std::atomic still doesn't have a copy constructor. Why is this code valid for -std=c++17?

Of course I know that the preferred style is to use {}, but I'm just curious why the code above compiles fine since C++17.

like image 871
Michal Avatar asked Jul 10 '21 13:07

Michal


1 Answers

Since C++17 such copy elision is guaranteed. For std::atomic<int> a = 0;, a is required to be initialized from 0 directly.

Note: the rule above does not specify an optimization: C++17 core language specification of prvalues and temporaries is fundamentally different from that of the earlier C++ revisions: there is no longer a temporary to copy/move from. Another way to describe C++17 mechanics is "unmaterialized value passing": prvalues are returned and used without ever materializing a temporary.

Before C++17, even though the copy/move operation (initializing a from the temporary std::atomic<int> which initialized from 0) might be optimized out (in the copy initialization), the copy/move constructor is still required to be accessible.

The last step is usually optimized out and the result of the conversion is constructed directly in the memory allocated for the target object, but the appropriate constructor (move or copy) is required to be accessible even though it's not used. (until C++17)

like image 165
songyuanyao Avatar answered Oct 11 '22 18:10

songyuanyao