Why atomic_flag default constructor leaves state unspecified? - c++

When using std::atomic_flag, one has to be careful to always explicitely initialize it using ATOMIC_FLAG_INIT, which is error-prone. However there is a default constructor... So, is there an objective reason behind having a default constructor leaving the flag in an unspecifiate state ?

This link (posted by dyp in comments), describes that this decision was made because on some architectures a zero-initialized atomic_flag would correspond to a set state, and on some it would correspond to a cleared state. Because of this, it was defined that an atomic_flag that is not explicitly initialized with ATOMIC_FLAG_INIT is initially in an indeterminate state.

This question was already answered by this answer
I had this issue come up with a map that contained a tuple that contained an std::atomic_flag - and putting in explicit initalization easily adds a lot of complicated code.
A workaround solution is to just wrap it in another type, such as this:
struct atomic_flag_ : public std::atomic_flag {
atomic_flag_() : std::atomic_flag{ ATOMIC_FLAG_INIT } {
}
};
or without inheritance:
struct atomic_flag_ {
std::atomic_flag flag{ ATOMIC_FLAG_INIT };
};
Now you don't have to worry about initalization (except in some special corner cases, like static init fiasco).

Related

Default struct initialisation in any case?

I realized that in C++ you can initialize any structure with default values. I don't think that was possible under C. Is that correct?
Are there situations in which it still makes sense not to use such a default initialization? Or is it better in any case since it is safer?
I also saw that there are different ways to do this.
Is One Method Better Than Another? Or is it just a matter of taste?
struct STR_Foo {
int value{ 0 };
};
struct STR_Foo {
int value = 0;
};
struct STR_Foo {
int value = { 0 };
};
I realized that in C++ you can initialize any structure with default values. I don't think that was possible under C. Is that correct?
Yes.
Are there situations in which it still makes sense not to use such a default initialization?
If you target Older standard than C++11 - or cross-compatibility with C. Default member initialisers weren't in the language before that - and aren't in C.
If you target C++11 standard and you want the class to be an aggregate. Since C++14 default member initialisers don't disqualify a class from being an aggregate.
If you need an instance of the class to be initialised later and have measured that you cannot afford the very low overhead of redundant initialisation.
I also saw that there are different ways to do this. Is One Method Better Than Another? Or is it just a matter of taste?
The choice to use = or not is stylistic when using curly brackets. Attempting to initialise without = and parentheses instead of curlies ends up being a function declaration for some cases, so you need to disambiguate by using = or curlies.
Curly brackets affect the form of initialisation in some cases. In cases where curlies and no curlies invoke the same constructor, using curlies is recommended because that syntax don't allow narrowing conversions. When curlies invoke a different constructor than no curlies, use the form that does what you need.
These apply to all initialisation; not just default members.

Initialization of POD types in constructor initialization lists

I find plenty of articles and SO questions about zero- and default-initialization of POD types, but I've not found any that discuss initialization of POD types as class members in class constructor initialization lists. I'm sure there's probably a SO question or article about it but I've not found any.
So if I have a class...
class MyClass
{
public:
MyClass() : anArrayOfInt() {}
private:
int anArrayOfInt[10];
}
...what can I know about the state of anInt after construction of a MyClass object? I've noted by empirical testing that with the above code on GCC 6.4.0, anArrayOfInt is all-zeros after a stack-allocated instance of MyClass is created, but if I change the code to this:
class MyClass
{
public:
MyClass() {}
private:
int anArrayOfInt[10];
}
...then stack-allocated instances no longer have all-zeros in anArrayOfInt. In my real case (the case that prompted me to write this question), this is causing test failures. I noted that if I change the code as follows:
class MyClass
{
public:
MyClass() { memset(anArrayOfInt, 0, sizeof(anArrayOfInt)); }
private:
int anArrayOfInt[10];
}
...then my tests again pass, even without listing anArrayOfInt() in the constructor initialization list. So it seems I need anArrayOfInt() in the initialization list, but before I revert back from the memset() version to the initialization list version, I need to know for certain that the initialization list entry "anArrayOfInt()" is guaranteed to zero the bytes of anArrayOfInt, or if that's just GCC's behavior and I can't count on it on other compilers.
If it matters, GCC 6.4.0 is where we run unit tests, but our target is the IAR embedded compiler for RX MCUs, which is still in C++03-land.
So if I have a class...
MyClass() : anArrayOfInt() {}
...what can I know about the state of anInt after construction of a MyClass object?
You've value initialised the member, so we know that it contains zeroes.
I need to know for certain that the initialization list entry "anArrayOfInt()" is guaranteed to zero the bytes of anArrayOfInt, or if that's just GCC's behavior and I can't count on it on other compilers.
Yes, value initialisation guarantees that integers are initialised to zero.

Why are mutexes and condition variables trivially copyable?

LWG 2424 discusses the undesirable status of atomics, mutexes and condition variables as trivially copyable in C++14. I appreciate that a fix is already lined up, but std::mutex, std::condition variable et al. appear to have non-trivial destructors. For example:
30.4.1.2.1 Class mutex [thread.mutex.class]
namespace std {
class mutex {
public:
constexpr mutex() noexcept;
~mutex(); // user-provided => non-trivial
…
}
}
Shouldn't this disqualify them as trivially copyable?
Either it was my mistake, or I was misquoted, and I honestly don't recall which.
However, I have this very strongly held advice on the subject:
Do not use is_trivial nor is_trivially_copyable! EVER!!!
Instead use one of these:
is_trivially_destructible<T>
is_trivially_default_constructible<T>
is_trivially_copy_constructible<T>
is_trivially_copy_assignable<T>
is_trivially_move_constructible<T>
is_trivially_move_assignable<T>
Rationale:
tldr: See this excellent question and correct answer.
No one (including myself) can remember the definition of is_trivial and is_trivially_copyable. And if you do happen to look it up, and then spend 10 minutes analyzing it, it may or may not do what you intuitively think it does. And if you manage to analyze it correctly, the CWG may well change its definition with little or no notice and invalidate your code.
Using is_trivial and is_trivially_copyable is playing with fire.
However these:
is_trivially_destructible<T>
is_trivially_default_constructible<T>
is_trivially_copy_constructible<T>
is_trivially_copy_assignable<T>
is_trivially_move_constructible<T>
is_trivially_move_assignable<T>
do exactly what they sound like they do, and are not likely to ever have their definition changed. It may seem overly verbose to have to deal with each of the special members individually. But it will pay off in the stability/reliability of your code. And if you must, package these individual traits up into a custom trait.
Update
For example, clang & gcc compile this program:
#include <type_traits>
template <class T>
void
test()
{
using namespace std;
static_assert(!is_trivial<T>{}, "");
static_assert( is_trivially_copyable<T>{}, "");
static_assert( is_trivially_destructible<T>{}, "");
static_assert( is_destructible<T>{}, "");
static_assert(!is_trivially_default_constructible<T>{}, "");
static_assert(!is_trivially_copy_constructible<T>{}, "");
static_assert( is_trivially_copy_assignable<T>{}, "");
static_assert(!is_trivially_move_constructible<T>{}, "");
static_assert( is_trivially_move_assignable<T>{}, "");
}
struct X
{
X(const X&) = delete;
};
int
main()
{
test<X>();
}
Note that X is trivially copyable, but not trivially copy constructible. To the best of my knowledge, this is conforming behavior.
VS-2015 currently says that X is neither trivially copyable nor trivially copy constructible. I believe this is wrong according to the current spec, but it sure matches what my common sense tells me.
If I needed to memcpy to uninitialized memory, I would trust is_trivially_copy_constructible over is_trivially_copyable to assure me that such an operation would be ok. If I wanted to memcpy to initialized memory, I would check is_trivially_copy_assignable.
Not all implementations provide a nontrivial destructor for mutex. See libstdc++ (and assume that __GTHREAD_MUTEX_INIT has been defined):
// Common base class for std::mutex and std::timed_mutex
class __mutex_base
{
// […]
#ifdef __GTHREAD_MUTEX_INIT
__native_type _M_mutex = __GTHREAD_MUTEX_INIT;
constexpr __mutex_base() noexcept = default;
#else
// […]
~__mutex_base() noexcept { __gthread_mutex_destroy(&_M_mutex); }
#endif
// […]
};
/// The standard mutex type.
class mutex : private __mutex_base
{
// […]
mutex() noexcept = default;
~mutex() = default;
mutex(const mutex&) = delete;
mutex& operator=(const mutex&) = delete;
};
This implementation of mutex is both standard conforming and trivially copyable (which can be verified via Coliru). Similarly, nothing stops an implementation from keeping condition_variable trivially destructible (cf. [thread.condition.condvar]/6, although I couldn't find an implementation that does).
The bottom line is that we need clear, normative guarantees, and not clever, subtle interpretations of what condition_variable does or doesn't have to do (and how it has to accomplish that).
It's important to look at this from a language lawyer perspective.
It's basically impossible for an implementation to implement mutex, condition variables, and the like in a way that leaves them trivially copyable. At some point, you have to write a destructor, and that destructor is very likely going to have to do non-trivial work.
But that doesn't matter. Why? Because the standard does not explicitly state that such types will not be trivially copyable. And therefore it is, from the perspective of the standard, theoretically possible for such objects to be trivially copyable.
Even though no functional implementation every can be, the point of N4460 is to make it very clear that such types will never be trivially copyable.

How to define a Struct with default values?

Rather surprised to find this question not asked before. Actually, it has been asked before but the questions are VERY DIFFERENT to mine. They are too complicated and absurd while I'll keep it simple and to the point. That is why this question warrants to be posted.
Now, when I do this,
struct A {
int a = -1;
};
I get the following error:
ANSI C++ forbids in-class initialization of non-const static member a
Now, along with the workaround can someone please tell me THE BEST way of initializing a struct member variable with a default value?
First, let's look at the error:
ANSI C++ forbids in-class initialization of non-const static member a
Initialization of a true instance member, which resides within the memory of an instance of your struct is the responsibility of this struct's constructor.
A static member, though defined inside the definition of a particular class/struct type, does not actually reside as a member of any instances of this particular type. Hence, it's not subject to explaining which value to assign it in a constructor body. It makes sense, we don't need any instances of this type for the static member to be well-initialized.
Normally, people write member initialization in the constructor like this:
struct SomeType
{
int i;
SomeType()
{
i = 1;
}
}
But this is actually not initialization, but assignment. By the time you enter the body of the constructor, what you've done is default-initialize members. In the case of a fundamental type like an int, "default-initialization" basically boils down to "eh, just use whatever value was in those bytes I gave you."
What happens next is that you ask i to now adopt the value 1 via the assignment operator. For a trivial class like this, the difference is imperceptible. But when you have const members (which obviously cannot be tramped over with a new value by the time they are built), and more complex members which cannot be default-initialized (because they don't make available a visible constructor with zero parameters), you'll soon discover you cannot get the code to compile.
The correct way is:
struct SomeType
{
int i;
SomeType() : i(1)
{
}
}
This way you get members to be initialized rather than assigned to. You can initialize more than one by comma-separating them. One word of caution, they're initialized in the order of declaration inside your struct, not how you order them in this expression.
Sometimes you may see members initialized with braces (something like i{1} rather i(c)). The differences can be subtle, most of the time it's the same, and current revisions of the Standard are trying to smooth out some wrinkles. But that is all outside the scope of this question.
Update:
Bear in mind that what you're attempting to write is now valid C++ code, and has been since ratification of C++11. The feature is called "Non-static data member initializers", and I suspect you're using some version of Visual Studio, which still lists support as "Partial" for this particular feature. Think of it as a short-hand form of the member initialization syntax I described before, automatically inserted in any constructor you declare for this particular type.
You could make a default constructor
struct A {
A() : a{-1} {}
int a;
};

When should we not use initialization list in the constructor?

Can someone please quote an example code when we should not use initialisation list in the constructor and how that can be overcome with assignment?
I am looking for an example for the below statement
This might happen when your class has two constructors that need to initialize the this object's data members in different orders. Or it might happen when two data members are self-referential. Or when a data-member needs a reference to the this object, and you want to avoid a compiler warning about using the this keyword prior to the { that begins the constructor's body (when your particular compiler happens to issue that particular warning). Or when you need to do an if/throw test on a variable (parameter, global, etc.) prior to using that variable to initialize one of your this members.
I believe the main concept that the author of your statement was referring to is the fact that calls made to variables in the initialisation list occur not in the order you see them in the initialisation list, but in the order the variables are listed in the class definition.
That means
if you have two different constructors which use initialisation lists, they must initialise them in the same sequence
your control over sequencing (which may be important if you have mutually-dependent members) is limited
I'd recommend taking a look at Scott Meyer's Effective C++ which covers this (amongst many, many other useful and informative topics).
Here are some examples:
This might happen when your class has two constructors that need to
initialize the this object's data members in different orders.
class Example1 {
public:
Example1(std::string decoded, std::string encoded)
: decoded_(decoded),
encoded_(encoded) {}
explicit Example1(std::string encoded)
: decoded_(), // Can't use "decoded_(Decode())" since "encoded_" isn't initialised
encoded_(encoded) {
decoded_ = Decode(); // Assign here instead of initialising
}
private:
std::string Decode(); // decodes class member "encoded_"
std::string decoded_, encoded_;
};
In this example, decoded_ will always be initialised before encoded_ since that's the order in which they are declared in the class, even if we swap their order in the initialisation list.
Or when a data-member needs a reference to the this object, and you
want to avoid a compiler warning about using the this keyword prior to
the { that begins the constructor's body (when your particular
compiler happens to issue that particular warning).
class Example2 {
public:
Example2() : functor_() {
functor_ = std::bind(&Example2::Do, this);
}
private:
void Do();
std::function<void()> functor_;
};
Here, functor_ needs to use this when it is initialised/assigned. If we were to intialise functor_ in the initialisation list, the this pointer would be referring to an object which at that point wasn't fully initialised. That could be safe depending on the particular circumstances, but the foolproof option is to defer setting functor_ until inside the constructor body, by which point this does refer to a fully-initialised object.
Or when you need to do an if/throw test on a variable (parameter,
global, etc.) prior to using that variable to initialize one of your
this members.
class Example3 {
public:
Example3(int force, int acceleration)
: force_(force),
acceleration_(acceleration),
mass_(0) {
if (acceleration_ == 0)
throw std::exception("Can't divide by 0");
mass_ = force_ / acceleration_;
}
private:
int force_, acceleration_, mass_;
};
Hopefully this is self-explanatory.
I'm not sure what is meant by
when two data members are self-referential
so I can't give an example for that I'm afraid.