|
-
June 11th, 2009, 12:07 AM
#1
Instantiating before the body is called?
I saw the following code in a friend's program
Code:
class ABC
{
public:
std::string PQ;
public:
testIt();
};
//the line below is where I have an issue
ABC::ABC(std::string boo) : PQ(boo)
{
//some code
}
He said it's declared that way, because the 'boo' value is being assigned to the PQ variable before the function body gets called.
My question is, why did C++ have a provision to assign a value in this way? Why not just assign it like
Code:
ABC::ABC(std::string boo)
{
PQ=boo;
//some code
}
Why did C++ provide the ": PQ(boo)" type of functionality?
-
June 11th, 2009, 12:16 AM
#2
Re: Instantiating before the body is called?
 Originally Posted by sd9
He said it's declared that way, because the 'boo' value is being assigned to the PQ variable before the function body gets called.
My question is, why did C++ have a provision to assign a value in this way?
This particular kind of assignment is actually initialisation to create the member variable with the given value rather than assigning a value to an existing member variable. The syntax is known as an initialisation list.
The use of an initialisation list would be necessary in some cases, e.g., to initialise const and reference member variables and those of types without a default constructor, or to invoke specific base class constructors.
-
June 11th, 2009, 01:24 AM
#3
Re: Instantiating before the body is called?
Oh....
I just google searched "initialization list" and tried to find out more about it. Necessary concept.
Thank you so much
-
June 11th, 2009, 07:02 AM
#4
Re: Instantiating before the body is called?
[QUOTE=laserlight;1850269]
The use of an initialisation list would be necessary in some cases, e.g., to initialise const and reference member variables and those of types without a default constructor, or to invoke specific base class constructors.[/QUOTE
A question about the last part "to invoke specific base class constructors": if I dont call a specific base class constructor, will the compiler automatically insert a call to default base class constructor in the initializer list?
I found this concept a little difficult to understand while transitioning from Java to C++; in java, you call specific base class constructors as the first line in the body of constructor. If you dont call a specific base class constructor, the compiler inserts a call to default constructor in the first line of body.
From what I understand, in C++, calls to base class constructor (user-specified or compiler inserted), all happen in the initializer list, and not in the first line of the body of constructor. Is that right?
thanks,
sgiri
-
June 11th, 2009, 09:31 AM
#5
Re: Instantiating before the body is called?
 Originally Posted by sgiri1981
A question about the last part "to invoke specific base class constructors": if I dont call a specific base class constructor, will the compiler automatically insert a call to default base class constructor in the initializer list?
Yes. (At least it can be understood that way.)
-
June 11th, 2009, 09:36 AM
#6
Re: Instantiating before the body is called?
 Originally Posted by sgiri1981
A question about the last part "to invoke specific base class constructors": if I dont call a specific base class constructor, will the compiler automatically insert a call to default base class constructor in the initializer list?
Also, please note:
All member variables of the class/struct are created by the compiler before the body of the constructor is called. If you have a member where it doesn't have a default constructor, you must tell the compiler how to create this member. You do this by supplying the member on the initialization list, along with the appropriate parameters to create the member successfully.
Code:
#include <string>
class foo
{
std::string x;
};
int main()
{
foo f;
}
So when f is created, when does the compiler invoke the constructor for the member variable "x"? The answer is in my first paragraph of this post. If std::string didn't have a default constructor, then you must tell the compiler how to construct it using the initialization list.
I found this concept a little difficult to understand while transitioning from Java to C++; in java, you call specific base class constructors as the first line in the body of constructor. If you dont call a specific base class constructor, the compiler inserts a call to default constructor in the first line of body.
Which is why I've stated many times on CodeGuru, don't use Java as a model in coding C++. The languages are not the same.\
Regards,
Paul McKenzie
Last edited by Paul McKenzie; June 11th, 2009 at 09:39 AM.
-
June 11th, 2009, 10:17 AM
#7
Re: Instantiating before the body is called?
 Originally Posted by Paul McKenzie
Also, please note:
All member variables of the class/struct are created by the compiler before the body of the constructor is called. If you have a member where it doesn't have a default constructor, you must tell the compiler how to create this member. You do this by supplying the member on the initialization list, along with the appropriate parameters to create the member successfully.
Code:
#include <string>
class foo
{
std::string x;
};
int main()
{
foo f;
}
So when f is created, when does the compiler invoke the constructor for the member variable "x"? The answer is in my first paragraph of this post. If std::string didn't have a default constructor, then you must tell the compiler how to construct it using the initialization list.
Regards,
Paul McKenzie
Thanks Paul. That was very helpful.
Continuing on this theme, lets say I have 2 members, one with and one without default constructor. The one without a default constructor MUST appear in the initializer list, however, the other NEED NOT, but for good programming practice, it is recommended. Is that right?
Also, when we say "compiler creates the members", what do you mean? are objects created and stored in obj and exe files as binaries? I thought objects are created at runtime on stack or on heap?
Thanks,
sgiri
-
June 11th, 2009, 10:26 AM
#8
Re: Instantiating before the body is called?
 Originally Posted by sgiri1981
Continuing on this theme, lets say I have 2 members, one with and one without default constructor. The one without a default constructor MUST appear in the initializer list, however, the other NEED NOT, but for good programming practice, it is recommended. Is that right?
I wouldn't particularly care about specifying initializers for default-constructed members, myself. In fact, my philosophy is---the more you can leave things to the compiler, the better off you are.
However, if you intend to give an initial value to a member, it is always more efficient to do so in the initializer list than in the constructor body.
There are some exception safety issues regarding the use of "new" in a constructor, but I don't understand them well enough to lay out the details.
Last edited by Lindley; June 11th, 2009 at 10:34 AM.
-
June 11th, 2009, 11:34 AM
#9
Re: Instantiating before the body is called?
There are some exception safety issues regarding the use of "new" in a constructor, but I don't understand them well enough to lay out the details.
If an exception is thrown in a constructor, the object's destructor will not be executed (however, the destructors of the object's members will run). Eg
Code:
class Foo
{
int* x;
public:
Foo( )
: x(new int)
{
throw 1;
}
~Foo( )
{
delete x;
}
};
void Frobnicate( )
{
Foo f;
}
int main( )
{
try
{
Frobnicate( );
}
catch (...)
{
}
return 0;
}
Foo::x is leaked, because the destructor is never executed. Basically if your class contains any non-RAII members, you have to manually be sure that those resources are freed on any exception, eg change the Foo ctor to
Code:
Foo( )
: x(new int)
{
try
{
throw 1;
}
catch (...)
{
delete x;
throw;
}
}
-
June 11th, 2009, 11:43 AM
#10
Re: Instantiating before the body is called?
 Originally Posted by Speedo
Basically if your class contains any non-RAII members, you have to manually be sure that those resources are freed on any exception
For a more comprehensive coverage of the issues involved, read GotW #66: Constructor Failures.
-
June 12th, 2009, 12:23 AM
#11
Re: Instantiating before the body is called?
 Originally Posted by sgiri1981
Also, when we say "compiler creates the members", what do you mean?
When the opening brace of the constructor body is executed, all members of the class must be already instantiated. And yes, the compiler creates those objects.
Again, look at my example -- when is the string object "x" created? Is it during the invocation of the constructor body, or before the constructor body is executed?
Regards,
Paul McKenzie
-
June 12th, 2009, 01:34 AM
#12
Re: Instantiating before the body is called?
 Originally Posted by laserlight
I found that article very interesting. I was in the middle of learning about exceptions when I took a break from my C++ book, so I have a few questions.
1) From the sound of the article, it seems like if a constructor throws an exception, you can not longer refer to anything that might have been allocated and so you can't delete them. Or does this only apply to things that are allocated with an initialization list? For example, would the following work. (Keep in mind, I'm not completely sure about exception syntax)
Code:
class Throws
{
private:
int * c;
public:
Throws(int num)
{
try
{
c = new int[num];
throw std:runtime_error("Example");
}
catch (. . .)
{
delete [] c;
throw;
}
}
};
I hope my intent comes across clearly enough. Just trying to grasp when you can prevent a potential link and when you couldn't if your using what I think the article referred to as unmanaged resource acquisition.
2) How often are exceptions used? When are they most useful?
3) The Pimpl idiom is mentioned a few times in there so I looked it up to find out what it is. Is it worth using to reduce compile times in a large project?
4) Going back to exceptions, the article states this:
Moral #6: If a constructor of a member object can throw but you can get along without said member, hold it by pointer and use the pointer's nullness to remember whether you've got one or not, as usual. Use the Pimpl idiom to group such "optional" members so you only have to allocate once.
Excluding the Pimpl part, what exactly does this mean? Does this mean that if class A has a member of class B, which can throw an exception, that you should declare the member as a pointer to B?
Code:
class A
{
B * b; //can throw an exception
//etc
}
Would you be able to successfully create an instance of A if initializing B int he constructor throws an exception? It doesn't seem to me that this is the case, so what is the point that the above statement is supposed to make?
-
June 12th, 2009, 01:53 AM
#13
Re: Instantiating before the body is called?
 Originally Posted by Raislin
1) From the sound of the article, it seems like if a constructor throws an exception, you can not longer refer to anything that might have been allocated and so you can't delete them. Or does this only apply to things that are allocated with an initialization list? For example, would the following work. (Keep in mind, I'm not completely sure about exception syntax)
It would work once you fix the typographical errors. The point here is that by the time the exception is propagated from the constructor, the necessary clean up has already been performed. However, you did miss one point: if an exception is thrown by the new[] expression, delete[] c would result in undefined behaviour since c was not initialised. You should write:
Code:
class Throws
{
public:
Throws(int num) : c(0)
{
try
{
c = new int[num];
throw std:runtime_error("Example");
}
catch (...)
{
delete[] c;
throw;
}
}
private:
int* c;
};
 Originally Posted by Raislin
2) How often are exceptions used? When are they most useful?
Read Stroustrup's answers to the FAQs Why use exceptions? and What shouldn't I use exceptions for?
 Originally Posted by Raislin
Does this mean that if class A has a member of class B, which can throw an exception, that you should declare the member as a pointer to B?
Well, Sutter does give the condition that "you can get along without said member".
 Originally Posted by Raislin
Would you be able to successfully create an instance of A if initializing B int he constructor throws an exception? It doesn't seem to me that this is the case, so what is the point that the above statement is supposed to make?
You would, since you could just catch and ignore the exception (possibly logging the error), leaving the pointer as a null pointer.
-
June 12th, 2009, 02:17 AM
#14
Re: Instantiating before the body is called?
 Originally Posted by laserlight
You would, since you could just catch and ignore the exception (possibly logging the error), leaving the pointer as a null pointer.
I didn't know you could ignore an exception. But I have yet to finish reading about them.
Thanks for the explanations. That all made perfect sense. Quick question: Is there any reason you prefer to put the private part of the class after the public part?
-
June 12th, 2009, 02:27 AM
#15
Re: Instantiating before the body is called?
 Originally Posted by Raislin
I didn't know you could ignore an exception.
If you catch and do nothing in the handler, you would be ignoring the exception.
 Originally Posted by Raislin
Quick question: Is there any reason you prefer to put the private part of the class after the public part?
As far as I know, this is common practice in C++, with the idea that readers of the class definition are more likely to be interested in the public members than in the non-public members, and in the protected members than in the private members. After all, every user of the class would need to know the public interface, those who derived from the class would need to know the protected interface, but only those who are maintaining the class need to know about the private implementation detail.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|