I looked at a piece of code and I am trying to understand how it works and so here is a minimal working example
template <typename T>
class A
{
public:
A() : _mem(T()) {};
private:
T _mem;
};
The first thing I was not exactly clear about is the initialisation of _mem in the initialiser list. What is this technique(?) called? If I look in the debugger _mem is set to 0. If there is a c++11 way to do the same thing could I receive some comments on that?
This is just to safeguard against an uninitialized A::_mem when T is a POD type or a built-in type (like an int). Using a constructor initializer list of : _mem(T()) will default construct a T and initialize _mem with it. For example:
struct POD {
int num;
};
// ...
A<POD> a;
Here, a._mem would be unitialized (in this case, this means a._mem.num is unitialized.) The : _mem(T()) prevents that from happening and will initialize a._mem.num to 0.
However, since C++11 you can just use inline initialization instead:
template <typename T>
class A {
public:
A() {};
private:
T _mem{};
};
T _mem{}; will default-construct _mem, which in turn means POD::num will be default-constructed, which for an int means it will be zero-initialized.
If this has a name, I don't know it.
What's happening:
T() constructs a temporary T and Zero Initializes it.
_mem(T()) makes _mem a copy of the temporary T. Note: A modern compiler will almost certainly elide the copy and simply zero initialize _mem. This still requires that T be copy-or-moveable, so _mem(T()) and _mem() are not exactly the same.
The only relevant C++ 11 difference I can think of is you can use curly braces, _mem{T{}}, for List Initialization. Not useful here, but very useful in other circumstances.
Related
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.
I am trying to understand the following code that I saw today. I already tried to find a related question, but since I have no idea what this feature of C++ is called it is hard to find related posts. A hint on the correct search term might already help me.
struct A
{ int x; };
struct B
{ B(A a) {}; };
int main()
{
B b{ { 5 } }; // works, seems to create a struct A from {5} and pass it to B's constructor
std::make_unique<B>({ 5 }); // doesn't compile
return 0;
}
Why is {5} not used to create a struct A when passed to make_unique but is used this way in the constructor of B?
If B had a second constructor B(int foo) {}; this one would be used instead of the one frome above (at least that is what I found by trial and error). What is the rule to decide if the argument is automatically used to create a struct A or if it is used directly as int in the constructor?
I am using Visual C++ 14.0
Here's a simplified demonstration:
struct X { X(int); };
void foo(X );
template <typename T> void bar(T );
foo({0}); // ok
bar({0}); // error
The issue is that braced-init-lists, those constructs that are just floating {...}s, are strange beasts in C++. They don't have a type - what they mean must be inferred from how they're actually used. When we call foo({0}), the braced-init-list is used to construct an X because that's the argument - it behaves as if we wrote X{0}.
But in bar({0}), we don't have sufficient context to know what to do with that. We need to deduce T from the argument, but the argument doesn't have a type - so what type could we possibly deduce?
The way to make it work, in this context, is to explicitly provide that T:
bar<X>({0}); // ok
or provide an argument that has a type that can be deduced:
bar(X{0}); // ok
In your original example, you can provide the A directly:
make_unique<B>(A{5})
or the B directly:
make_unique<B>(B({5}))
or just use new:
unique_ptr<B>(new B({5}))
or, less preferred and somewhat questionable, explicitly specify the template parameter:
make_unique<B, A>({5});
A constructor with a single non-default parameter (until C++11) that is declared without the function specifier explicit is called a converting constructor. Your A and B are instances of such constructors (this explains, why your first call works fine.) The problem is, that std::make_unique impedes these explicit calls. Anyhow, it might be a good idea, to not trust in these automatic creation in the first place and spent a few chars to show types. This could improve the readability of the code.
It seems empirically that C++ always prefers a list initializer over a value initializer. My question is thus how can I force value initialization of a type that also supports a direct list initialization. Here is a minimal non-working example:
#include <initializer_list>
using namespace std;
struct foo {
foo(int) {}
foo(initializer_list<char>) {}
};
struct bar {
foo f{256};
};
In this example, I would like f to be initialized using the constructor foo(int) rather than the foo(initializer_list<char>). However, both GCC and Clang reject the code because 256 is too big for a char, which means the C++ spec requires choosing the list initializer. Obviously commenting out the second constructor of foo fixes the problem. What's the easiest way to define bar so as to use value initialization on field f? Ideally I could avoid copy initializing f, because in my real example there is no copy constructor.
update
To clarify: of course it's possible to initialize f explicitly in every single constructor of bar. But my question is specifically about the member initialization syntax because in situations with huge numbers of constructors it is preferable just to initialize certain fields in one place rather than to copy the code all over.
So long as you require foo to be non copyable/moveable, and you require foo to have an initializer_list constructor that could be used instead of a constructor, this is the behavior you get. Therefore, you have to change one of these facts if you want to solve this problem.
If you cannot change the definition of foo at all, then you're screwed. Complain to whomever owns the class.
The second fact is probably the easiest to change, but even that will not be without consequences:
struct il {};
struct foo {
foo(int) {}
foo(il, initializer_list<char>) {}
};
This completely disambiguate the problem. foo{256} will always call the single-integer constructor. However, foo technically has no initializer_list constructors; you instead must use the tag type il to call it with an initializer list of values:
foo f{il{}, {/*actual list*/}};
This requires more braced, but there is no real alternative.
Note that in C++17, guaranteed elision lets you do this:
struct bar {
foo f = foo(256);
};
Regardless of whether foo is mobile or not.
I am working on Michael J Laszlo's Book 'Computation Geometry and Computer Graphics in C++' .
The following is a template class prototype:
template <class T> class ListNode : public Node {
T _val;
ListNode (T val);
friend class List<T>;
};
template <class T> ListNode <T>::ListNode(T val)
{_val=val;};
template <class T> class List{
private:
ListNode <T> *header;
ListNode <T> *win;
int _length;
public:
List(void);
~List(void);
T insert(T);
T append(T);
List * append(List*);
T prepend(T);
T remove(void);
void val(T); // overloaded function!
T val(void);// overloaded function!
T next(void);
T prev(void);
T first(void);
T last(void);
int length(void);
bool isFirst(void);
bool isLast(void);
bool isHead(void);
};
Now look at the way he defines the List constructor:
// constructors and destructors
template <class T> list<T>:: List(void): _length(0)
{
header =new ListNode<T>(NULL);
win=header;
}
My Question:
What is up with the assigning a default length outside the {...} and the rest inside? Is there some sort of logical reasoning behind this?
Because for example before this, he pretty much declared everything outside the {...} and I assumed that was just his style
What is up with the assigning a default length outside the parenthesis and the rest inside the curly braces?
This is very common and desirable. The construct is called initialization list. For example, this
template <class T> ListNode <T>::ListNode(T val)
{_val=val;};
can be rewritten as this:
template <class T> ListNode <T>::ListNode(T val)
: _val(val) {};
Using this construct instructs the compiler to use copy constructors for items being copied, rather than using default constructors followed by assignment operators. In case of assigning primitives it hardly matters, but with more complex types initialization lists could save you some CPU cycles.
The reason the author did not put the header and win assignments into the initialization list is to force a particular order of initialization where it matters. The assignment to header must happen before the assignment to win. When you use initialization lists, the order of assignments is not controlled by the order of items in the list: instead, it is controlled by the relative order of declaration of the corresponding members in the class. Relying upon it is very confusing to the reader and too fragile to remain in production, so the author correctly decided to move the two assignments into the body of the constructor.
The way I'm reading the question, you're not asking why _length is initialised in the initialiser list, but you're asking why header and win aren't.
Suppose you had
template <class T> List<T>::List(void)
: _length(0)
, header(new ListNode<T>(NULL))
, win(header)
{ }
What would this do? Would this initialise header and then copy it to win, or would this first copy header to win and only then set header? You cannot tell by looking at the constructor definition. You can tell by looking at the constructor definition when plain old assignments are used. So some (myself included) might say the code is easier to read the way it is.
It is for efficiency reason. That region -- before the {} and after the () is called initializer list. You can initialize your variable there. The compiler instead of default initializing your member variables will initialize the variables set in that initializer list.
Compare it to the scenerio where you initialize your variable inside the {}. The compiler first initializes all your member variable then goes into the body, {}, then you re-initialize your member variables. The initializer skips that initialization step. Always initialize in the initializer-list when possible.
Firstly, it is more efficient to define values in the initialiser list. If you don't do this, unless you have a clever compiler, the values will be default initialised, and the assigned to. For some types, this is not terribly efficient (although not in the class you have there).
As to why he decided to do it this way for this one class, it's unclear. I can only assume it is so that he can perhaps catch the possible throw from the new in an out of memory situation - although even there he could do a new(nothrow) for that which would probably be both more efficient and clearer.
What he could be trying to do is not to fall foul off the order of initialisation requirements of C++ - class members are initialised in the order they are declared in the class definition, not in the order you specify them in the constructor initialisation list. That can be a real pain, though most compilers now warn you if you are doing that (and also allow you to change that warning into an error). In this case, it would be possible for win to have been declared before header, in which case doing win(header) in the initialiser list would set win to have the value of header, before header got initialised. Although, even there, I'd still have initialised header in the initialiser list, and only put the initialisation of win in the code block.
What really irks me is his use of (void) parameter lists. That's a C-ism, and looks ugly. Especially for default constructors and destructors.
Suppose I have got the following template
template <typename T>
class{
T t;
};
Now, I want to add a constructor that initializes t with the default value for its type. That is, for numerical types, t should be initialized with 0, for pointers, t should be initialized with nullptr. Finally, there could be other types like structs. Here, a good initialization would be the default constructor (which is invoked anyway, so I do not have to do anything here).
In conlusion I am looking for something like this:
template<typename T>
class X{
T t;
X() : t(default_value<T>::value);
}
As my imaginary syntax points out, I think it could be possible with some kind of template with different specializations which carry the default values. But how to handles structs and classes? Since I have specified t(...), the default constructor is no longer an option.
You can just do
X() : t() { }
And/or this in C++11
X() : t { } { } // see Johannes Schaub's comments about this
That will value initialise (or is it default initialisation?) t to whatever the default value is for its type, be it 0 for built-in's, a series of (value?default) initialisations for arrays, or using the default constructor for user-defined types.