I have a simple object that holds some [public] data.
I want to keep my interface clean, so I don't want to pre-/post- fix anything to the names of the publically accessible variables nor to the names of my function arguments.
That said, I ended up doing something like this:
template<typename T> struct Foo
{
explicit Foo(T x) : x(x) // This [i.e., x(x)] seems to be doing the "Right Thing", but is this well defined?
{/* ^
No pre-/post- fixing.
*/
}
T x; // No pre-/post- fixing.
};
Just to reiterate: All I'm asking is whether this is well defined behavior. Not whether I should or shouldn't be doing this...
Thanks.
Yes, that's fine, and perfectly standard.
Local variables always come first in a name lookup, but the x(...) in an initialization list can obviously only refer to member variables [edit:or a base class].
If you didn't use the initialization list, you would have to write:
explicit Foo(T x)
{
this->x = x;
}
Specifically for the initializer list of a ctor, it's well-defined behavior -- since you can only initialize a member or base class, there's no ambiguity between one of those and the name of a parameter.
Under almost any other circumstance, however, you'll create an ambiguity. In particular, your title simply refers to "function" -- and for any function other than the ctor, this won't work. Even inside the body of the ctor, it won't work -- the "special" treatment is purely within the initializer list of a ctor.
Related
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.
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;
};
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.
I am a beginner in C++ and am trying to learn it by looking at examples.
Here is an example definition for a class that I don't understand the meaning completely:
class MyClass{
public:
std::string name;
void *data;
MyClass(const std::string& t_name, void *t_data) : name(t_name), data(t_data) {}
};
Here is what I understand:
name and *data are variables of the class and, MyClass(...) is the constructor. The meaning of : is the left side class is derived from the right hand side class. However, what is the meaning of this part of the code:
MyClass(const std::string& t_name, void *t_data) : name(t_name), data(t_data) {}
Here are the questions:
what are "t_data" and "t_name"? Are they initial values for "data" and "name"? what is the reason t_ is used here?
what is the meaning of : in the above line?
what is {} at the end of that line?
Thanks for the help.
TJ
what are "t_data" and "t_name"? Are they initial values for "data" and "name"?
They are the arguments passed to the constructor. If an object were created as
MyClass thing("Fred", some_pointer);
then, in the constructor, t_name has the value "Fred" and t_data has the value of some_pointer.
what is the reason t_ is used here?
Some people like to tag the arguments to give them different names to the class members, but there's no need to do that unless you want to.
what is the meaning of : in the above line?
That marks the start of the initialiser list, which initialises the class member variables. The following initialisers, name(t_name), data(t_data) initialise those members with the constructor's arguments.
what is {} at the end of that line?
That's the constructor's body, like a function body. Any code in their will be run after the members have been initialised. In this case, there's nothing else to do, so the body is empty.
It is good C++ practice to use initializer lists to initialize members.
t_name, t_data are the parameter names.
The "t_" prefix is merely used to distinguish it from the similarly named member fields.
The members are being initialized using syntax that resembles a function call, but it is a proper initialization/construction, so you should think of it that way.
The colon signals the beginning of an initializer list
The empty braces {} designate that the body of the constructor (which happens after the members are initialized) is empty.
MyClass(const std::string& t_name, void *t_data) : name(t_name), data(t_data) {}
is constructor of your class, and you should initialize your class with a string and void* parameter, then you initialize your class fields (name and data) with your passed parameters
This is a somewhat compressed example for a beginner, but you're asking good questions.
1) t_data and t_name are the parameters going into the constructor. When you create an instance of this class, you'll do something like:
MyClass * myNewClassInstance = new MyClass("My name", &myData);
Now the constructor has "My name" (in std::string form) as t_name and a pointer to myData as t_data.
2) The colon here does not refer to a derived class. Here it says that an "initializer list" is to follow. Check out Prashant's answer's link, or do a little digging about this. Basically, this is setting the member variable name to t_name (which is the std::string that we passed into the constructor in the above example), and data to t_data (the void pointer). (see additional notes below)
3) The {} is the actual definition of the constructor. It's empty -- there's no code here. So all the constructor will do is initialize the member variables (as defined by the initializer list), and nothing more.
Now let's look at the exact same class in a more beginner-friendly format:
// The declaration of MyClass. This would often show up in a header (.h) file
class MyClass {
public:
// Member variables
std::string name;
void * data;
// Declaration of constructor -- we haven't defined what actually does here, just
// what parameters it takes in.
MyClass(const std::string& t_name, void * t_data);
}
// We declared what the class "looks like" above, but we still have to define what
// the constructor does. This would usually show up in a .cpp file
// This is the constructor definition. We have to specify that it's part of the
// The extra "MyClass::" specifies that it's part of the MyClass namespace that we
// declared above.
MyClass::MyClass(const std::string& t_name, void * t_data)
{
// Set our member variables to what was passed in.
this.name = t_name;
this.data = t_data;
}
The above version does exactly the same thing (with some subtle differences between initializer lists and traditional initialization in the constructor that you probably don't care about yet -- again, see other references regarding this if you're curious).
It's pretty obvious that this takes up a lot more space, and that's exactly why the more compressed format is often used. But when you're just starting out, it makes things a lot more clear doing it this way. It's important to understand the difference between a declaration and a definition when it comes to functions (i.e. the constructor), because the example you posted does both at the same time when often they are separated.
I am a beginner in C++ and am trying to learn it by looking at examples.
For whatever reason, this is harder to do in C++ than it is in Perl, Python, Java, or even C. I don't recommend this course; instead, you might invest in a good book.
Here is what I understand:
Let's start with that. I don't think you understand as much as you claim to.
name and *data are variables of the class
No. name and data are variables of the class. Their types are std::string and void*, respectively.
MyClass(...) is the constructor.
Yes.
The meaning of : is the left side class is derived from the right hand side class.
No, : means different things in different contexts. In the context in which it is used in your sample, it indicates that an initializer list follows.
However, what is the meaning of this part of the code:
what are "t_data" and "t_name"?
They are local variables in the constructor function. Specifically, they are the passed-in parameters to the function.
Are they initial values for "data" and "name"?
That is how they are being used in this sample. Specifically, they are being passed to the data and name initializers in the initializer list.
what is the reason t_ is used here?
This is purely the convention of this particular author. I've never seen that convention before.
what is the meaning of : in the above line?
It introduces an initializer list. This construct is only used in constructor member functions. Each named member is initialized by the values listed. (Note: the values do not need to come from parameters -- they can be any legal expression, so: MyClass(int ii) : i(ii), j(cos(0) / 2), k(&global_variable) {} might be a legitmate constructor. )
what is {} at the end of that line?
The body of the constructor member function. Since all of the work of the constructor is being done in the initializer list, the body of the function is empty.
the question is simple...
is there any difference in using this->yourvariable or yourvariable directly for some reason?
I am not finding any problem with that, but I am using this-> a lot and would like to know if there is any difference before going further.
I saw a comment on a post here and I don't remember which thread, but the person said something about using the keyword "this".
Personally, I find it nice to use than the variable directly. It makes the code more easier and pretty.
Joe
In most cases there is no difference. But there are situations where it makes a difference:
class foo
{
int i;
void bar() {
int i = 3;
i; // refers to local i
this->i; // refers to the member i
}
};
Also, with templates you may need to qualify a member with this-> so that name lookup is delayed:
template<typename T>
struct A
{
int i;
T* p;
};
template<typename T>
struct B : A<T>
{
void foo() {
int k = this->i; // here this-> is required
}
};
A compiler that properly does the "two phase lookup" will complain in case you remove "this->" that it doesn't know what i is supposed to be. "this->" tells it that it's a member from a base class. Since the base class depends on a template parameter, lookup is delayed until the class template is instantiated.
No, there is no real difference, it is simply a scope qualifier. However, suppose a method
void SetFoo( Foo foo )
{
this->foo = foo;
}
where this->foo is a private member. Here it allows you to take a parameter with the same name as a class/instance variable.
I find that using this makes my code more readable, but there's no reason that you have to. If you look at the assembler code your compiler generates, it should be functionally (and usually literally) identical.
Basically, when the function is called, it is passed a hidden argument this which is then used to figure out which variables are where. If you use the variables directly, without a this->, you're not doing anything except making use of some syntactic sugar.
This was kind of asked and answered about C# here and I think that the answer (at least mine) is the same. It is preference.