Can I pass "this" to a function as a pointer, from within the class constructor, and use it to point at the object's members before the constructor returns?
Is it safe to do this, so long as the accessed members are properly initialized before the function call?
As an example:
#include <iostream>
class Stuff
{
public:
static void print_number(void *param)
{
std::cout << reinterpret_cast<Stuff*>(param)->number;
}
int number;
Stuff(int number_)
: number(number_)
{
print_number(this);
}
};
void main() {
Stuff stuff(12345);
}
I thought this wouldn't work, but it seems to. Is this standard behavior, or just undefined behavior going my way?
When you instantiate an object in C++, the code in the constructor is the last thing executed. All other initialization, including superclass initialization, superclass constructor execution, and memory allocation happens beforehand. The code in the constructor is really just to perform additional initialization once the object is constructed. So it is perfectly valid to use a "this" pointer in a class' constructor and assume that it points to a completely constructed object.
Of course, you still need to beware of uninitialized member variables, if you haven't already initialized them in your constructor code.
You can find a good answer to this here (C++ FAQ).
All inherited members and members of the calling class are guaranteed to have been constructed at the start of the constructor's code execution and so can be referenced safely within it.
The main gotcha is that you should not call virtual functions on this. Most times I've tried this it just ends up calling the base class's function, but I believe the standard says the result is undefined.
As a side-note on the presented code, I would instead templatize the void*:
class Stuff
{
public:
template <typename T>
static void print_number(const T& t)
{
std::cout << t.number;
}
int number;
Stuff(int number_)
: number(number_)
{
print_number(*this);
}
};
Then you'd get a compile error if the type of t doesn't have a number member.
Andy, I think you're wrong about the undefined part of the standard.
When you're in the constructor, "this" is a pointer to an object whose type is the base class of the object you're creating, which means that virtual functions partially implemented in the base class will be called and the pointers in the virtual table won't be followed.
More info in the C++ Faq Lite...
Related
i ran into a segfault running the following program
#include <iostream>
#include <vector>
template <typename Derived>
struct CRTPBase {
CRTPBase() {
func();
}
void func() {
static_cast<Derived*>(this)->_func();
}
};
struct CRTPChild : CRTPBase<CRTPChild>{
using CRTPBase<CRTPChild>::CRTPBase;
void _func(){
vec.resize(10);
vec[0] = 2;
}
std::vector<int> vec;
};
int main()
{
CRTPChild obj;
std::cout << obj.vec[0] << std::endl;
}
When i replace vec with a member of type int it doesn't segfault anymore. Why?
Your code has undefined behavior. The problem comes from the order of the initialization; for the derived class CRTPChild, the constructor of the base class CRTPBase<CRTPChild> is invoked firstly, after that the data member vec of CRTPChild get initialized. When _func is invoked (from the constructor of the base class) vec is not initialized at all.
2) Then, direct base classes are initialized in left-to-right order as
they appear in this class's base-specifier list
3) Then, non-static data members are initialized in order of
declaration in the class definition.
Changing the type to int it's still UB. UB means anything is possible, it might lead to segfault or might not.
When CRTPBase constructor is called, CRTPChild is not yet fully constructed, so calling it's member function is undefined behavior.
The way undefined behavior manifests itself depends on platform, compiler and phase of the moon.
In particular, when your member is an int, the fact that it is not yet constructed doesn't cause program to crash when you are using int - there are no invariants for int. Vector, on the other hand, has invariants, so accessing unconstructed vector will violate them, and cause incorrect memory access.
The base-class will be initialized (i.e. constructed) before the child class. That means when you call CRTPChild::_func the CRTPChild part of the object (including the vector) haven't been constructed yet. Using the vector in any way will lead to undefined behavior.
Don't access (non-static) members of child-classes in a base-class constructor.
i ran into a segfault running the following program
#include <iostream>
#include <vector>
template <typename Derived>
struct CRTPBase {
CRTPBase() {
func();
}
void func() {
static_cast<Derived*>(this)->_func();
}
};
struct CRTPChild : CRTPBase<CRTPChild>{
using CRTPBase<CRTPChild>::CRTPBase;
void _func(){
vec.resize(10);
vec[0] = 2;
}
std::vector<int> vec;
};
int main()
{
CRTPChild obj;
std::cout << obj.vec[0] << std::endl;
}
When i replace vec with a member of type int it doesn't segfault anymore. Why?
Your code has undefined behavior. The problem comes from the order of the initialization; for the derived class CRTPChild, the constructor of the base class CRTPBase<CRTPChild> is invoked firstly, after that the data member vec of CRTPChild get initialized. When _func is invoked (from the constructor of the base class) vec is not initialized at all.
2) Then, direct base classes are initialized in left-to-right order as
they appear in this class's base-specifier list
3) Then, non-static data members are initialized in order of
declaration in the class definition.
Changing the type to int it's still UB. UB means anything is possible, it might lead to segfault or might not.
When CRTPBase constructor is called, CRTPChild is not yet fully constructed, so calling it's member function is undefined behavior.
The way undefined behavior manifests itself depends on platform, compiler and phase of the moon.
In particular, when your member is an int, the fact that it is not yet constructed doesn't cause program to crash when you are using int - there are no invariants for int. Vector, on the other hand, has invariants, so accessing unconstructed vector will violate them, and cause incorrect memory access.
The base-class will be initialized (i.e. constructed) before the child class. That means when you call CRTPChild::_func the CRTPChild part of the object (including the vector) haven't been constructed yet. Using the vector in any way will lead to undefined behavior.
Don't access (non-static) members of child-classes in a base-class constructor.
This surprised me a little bit, but I was playing around with some code and found out that, at least on my computer, when a function accepts a parent class by reference and you pass a child instance, that the slicing problem doesn't occur. To illustrate:
#include <iostream>
class Parent
{
public:
virtual void doSomething()
{
using namespace std;
cout << "Parent::DoSomething" << endl;
}
};
class Child : public Parent
{
public:
virtual void doSomething()
{
using namespace std;
cout << "Child::DoSomething" << endl;
}
};
void performSomething(Parent& parent)
{
parent.doSomething();
}
int main(int argc, char** argv)
{
Child myChild;
performSomething(myChild);
return 0;
}
This prints out Child::DoSomething.
Like I said, I was a little surprised. I mean, I know that passing by reference is like passing pointers around (but much safer in my understanding), but I didn't know I still got to keep polymorphic goodness when doing so.
I just want to make sure, is this supposed to happen or is it one of those "it works on my machine" type of instances?
"Slicing" refers to the inability of the base copy constructor to distinguish exact type matches from derived classes. The only way to invoke slicing is to invoke the base copy constructor. Typically this occurs when passing arguments by value, though other situations can be contrived:
class Base { };
class Derived : public Base { };
void foo(Base);
int main()
{
Derived x;
Base y = x; // flagrant slicing
foo(x); // slicing by passing by value
}
You're never doing any such thing, so you do not encounter any slicing situations.
The behavior you are seeing is correct. This is how it is supposed to work. References work just like pointers.
That's supposed to happen. Passing by reference is EXACTLY like passing pointers -- it's doing the same thing under the hood. There's no magic to this; every instance of a polymorphic object has a virtual function table associated with it. As long as you don't copy anything, you're not going to lose that information and your virtual function calls will work the way you expect they would.
The reason that you run into problems when passing by value is that it will use the copy constructor of the type you specified in the function signature, so you end up with an entirely new instance of the superclass.
Yes, binding to a reference enables dynamic binding. This is caused by the difference of the dynamic type of an object and its static type.
If you take your parameter by value, it becomes a Parent class. Although if you pass something through a reference or a pointer and call a virtual function, the run-time will look for the dynamic type or most-derived type of the actual object that is being referenced.
creating an object using a constructor and along with that calling functions of object which is being constructed:
class A
{
public:
A()
{
this->show();
}
void show()
{
cout<<"show called!";
}
};
and now i m creating object in main() as below:
int main()
{
A a;
int xy;
cin>>xy;
return 0;
}
my doubt is that when i am creating an object using constructor then how i am able to call object function while object is not fully constructed?
virtual function calls:
class A
{
public:
A()
{
}
virtual void show()
{
cout<<"show called!";
}
};
class B:public A
{
public:
B()
{
A *a=this;
a->show();
}
void show()
{
cout<<"derived show";
}
};
int main()
{
A a;
B b;
int xy;
cin>>xy;
return 0;
}
working fine with output: derived show
It's fine to call virtual functions and non-static member functions:
See section 12.7 of http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf:
4 Member functions, including virtual functions (10.3), can be called
during construction or destruction (12.6.2).
However when using virtual functions in a constructor there are some restrictions. It's a bit of a mouthful:
When a virtual function is called directly or indirectly from a
constructor (including the mem-initializer or
brace-or-equal-initializer for a non-static data member) or from a
destructor, and the object to which the call applies is the object
under construction or destruction, the function called is the one
defined in the constructor or destructor’s own class or in one of its
bases, but not a function overriding it in a class derived from the
constructor or destructor’s class, or overriding it in one of the
other base classes of the most derived object (1.8).
I interpret the above paragraph as saying the virtual functions called will not be in any derived class. This makes sense because at this point in the execution phase any constructor in a derived class will not have begun execution.
Additionally part 1 places a restriction that use of non-static members should occur after the construction begins. In your example the members are being invoked after the construction begins, so you're not violating part 1:
1 For an object with a non-trivial constructor, referring to any
non-static member or base class of the object before the constructor
begins execution results in undefined behavior.
This code is completely legal. You can call methods
in the class constructor.
All constants (from the initialization list) are already initialized and all base class constructors are called.
However, You should not call virtual methods in the constructor. See Scott Meyers explanation for this restriction.
The thing to think about is, which parts of the object are constructed at the time when you call show()?
Since you call show() from within your constructor's body (and not e.g. from within the constructor's initializer list) you can rest assured that all of the A object's member variables have already been constructed (since that happens before the constructor body is executed).
What might trip you up would be if show() was a virtual method, and A::A() was being called from the constructor of a subclass of A. In that case, you might want show() to call B::show(), but that won't happen because the vtable for B hasn't been set up yet (you would end up calling A::show() instead, or crashing the program if A::show() was a pure-virtual method)
You are calling a function in an partially constructed object, which may result in erroneous behavior if such function deals with class members and such. I am not sure whether its invoking undefined behaviour or not, but I don't think its a good practice. And the situation gets worse with inheritance and virtual functions!
In your example, show could be declared static and there will be no risk in calling it.
Consider a class as 2 separate parts: The object containing fields (variables) and the methods (functions). The methods of a given class exist independent of any particular instance, so it can be called at any time by a valid instance, even mid-construction.
The fields are "created" when the object is instantiated, before the constructor is run. However, they have no values set to them. So, if your constructor calls any methods BEFORE the fields are initialised to sensible values, then you're going to experience some undefined behaviour.
Whenever possible, if you must call a method inside a constructor, be sure to initialise as many fields as possible to sensible values.
my doubt is that when i am creating an object using constructor then how i am able to call object function while object is not fully constructed?
what happens in your example is fine, as long as you initialize where you are supposed to (the initialization list). you are using static dispatch on an object which has initialized members (specifically, A has no such variables to initialize).
what then is invalid?
not initializing your members correctly, or using them before they are really initialized. favor the initialization list without using this.
using dynamic dispatch from within your constructor's body (or initializer). your object is not fully constructed.
unusually, you could also attempt to typecast it to a subclass from the constructor.
I'd like to do this:
struct Derived;
struct Base{
Derived const& m_ref;
Base(Derived const& ref) : m_ref(ref){}
};
struct Derived: Base{
Derived(): Base(*this){}
};
But I seem to get unreliable behaviour (when used later on, m_ref points to things that aren't valid Derived).
Is it permissible to construct a reference to Derived from *this before the class has been initialised?
I appreciate that it is not valid to use such a reference until it has been initialised, but I don't see how changes to the initialisation of a class can affect references to it (since initialising it doesn't move it around in memory...).
I'm not sure what to call what I'm trying to do, so my search for information on this has drawn a blank...
Update:
I can't reproduce my problems with a simple test case, so it looks like it is probably okay (though I can't prove it, and would still welcome a definitive answer).
Suspect my problems arose from a broken copy-assignment operator. That's another matter altogether though!
Update 2
My copy constructor and copy-assignment operators were indeed to blame, and now this seems to work reliably. Still interested in whether or not it is well-defined behaviour though.
3.8/1 says:
The lifetime of an object of type T
begins when: — storage with the proper
alignment and size for type T is
obtained, and — if T is a class type
with a non-trivial constructor (12.1),
the constructor call has completed.
3.8/5 says:
Before the lifetime of an object has started but after the storage which the object will occupy has been allocated
or, after the lifetime of an object has ended and before the storage which the object occupied is
reused or released, any pointer that refers to the storage location where the object will be or was located
may be used but only in limited ways. Such a pointer refers to allocated storage (3.7.3.2), and using the
pointer as if the pointer were of type void*, is well-defined. Such a pointer may be dereferenced but the
resulting lvalue may only be used in limited ways, as described below.
"Below" is 3.8/6:
Such an lvalue refers to allocated storage (3.7.3.2), and using the properties of the lvalue which do not
depend on its value is well-defined.
...and then a list of things you can't do. Binding to a reference to the same, derived type is not among them.
I can't find anything elsewhere that might make your code invalid. Notably, despite the following phrase in 8.3.2/4:
A reference shall be initialized to
refer to a valid object or function.
there doesn't seem to be any definition of "valid object" to speak of.
So, after much to-ing and fro-ing, I must conclude that it is legal.
Of course, that's not to say that it's in any way a good idea! It still looks like a bad design.
For example, if you later change your base constructor and any of the following become relevant (again from 3.8/6):
the lvalue is used to access a non-static data member or call a non-static member function of the object
the lvalue is implicitly converted (4.10) to a reference to a base class type
the lvalue is used as the operand of a static_cast (5.2.9) (except when the conversion is ultimately to char& or unsigned char&
the lvalue is used as the operand of a dynamic_cast (5.2.7) or as the operand of typeid.
...then your program will be undefined, and the compiler may emit no diagnostic for this!
Random other observations
I notice a couple of other interesting things whilst compiling this answer, and this is as good a place as any to share them.
First, 9.3.2 appears to leave the type of this in a ctor-initializer accidentally unspecified. Bizarre!
Second, the criteria set on a pointer by 3.8/5 (not the same list that I quoted from 3.8/6) include:
If the object will be or was of a
non-POD class type, the program has
undefined behavior if [..] the
pointer is implicitly converted (4.10)
to a pointer to a base class type.
I believe that this renders the following innocuous-looking code undefined:
struct A {
A(A* ptr) {}
};
struct B : A {
B() : A(this) {}
};
int main() {
B b;
}
I think in general you're OK doing this, but be very careful in constructors and destructors. In particular, in Base::~Base, the Derived part of the object has already been destroyed so don't use m_ref there.
3.8/6 says what you can do with a pointer/reference to memory for an object that has been allocated but not yet constructed. Your code doesn't provoke an lvalue-to-rvalue conversion, or otherwise break the rules, so I'd think that you're fine. Since you're observing bad values, though, I may well have missed something. Or your code might be otherwise bad.
Even if you did break those rules, 12.6.2 and 12.7 list additional things that you can do during construction and destruction.
Edit: ah, 8.3.2/4: "A reference shall be initialized to refer to a valid object
or function." You initialize m_ref to refer to an object whose constructor hasn't even been entered yet. I don't know without further research whether an object under construction is "valid" or not, and in particular whether the object of most-derived type is "valid" at the time of construction of the base class. This could perhaps be the problem, though.
You might think that no unconstructed object is "valid", but then this would be invalid:
class Foo {
Foo() {
Foo &self = *this; // reference initialized to refer to unconstructed object!
}
};
So, is that invalid? If not, does the most-derived object become valid somewhere between the start of the base class constructor call and the start of the derived class constructor call? I dunno, sorry.
I think the big problem in this is that you think you want to do one thing, when in reality you actually want to do something else. Strange, huh?
Is it permissible to construct a reference to Derived from *this before the class has been initialised?
Yes, as long as you don't use it (for anything but storing a reference to it) in the scope of the Base constructor and remember in ~Base that Derived is destroyed before Base.
But why on earth do you think that Base wants to know of Derived? If it's static polymorphism you are after, then the curiously recurring template pattern is what you want:
template <typename T>
class Base {};
class Derived : public Base<Derived> {};
But I don't really think that's what you're aiming at.
Maybe you want a way for Base to communicate with a client and think that should be done with inheritance? If so, then this observer-ish idiom is what you need:
class Client
{
public:
virtual void Behavior() = 0;
protected:
~Client() {}
};
class Base
{
Client& client_;
public:
Base(Client& client) : client_(client) {}
};
class Implementor : public Client
{
public:
Implementor() : Base(*this) {}
virtual void Behavior() { ... }
};
If not even that is what you want, then you need to rethink your design.
I'm actually implementing a generic base class that takes a template parameter class and derives from it, and adds a "safe bool" conversion based on the result of a function call on the derived type. I'd like to avoid using virtual functions, if possible, because I'm a serial premature optimiser I really do care about performance in some of the places I'd like to use this. – Autopulated 37 mins ago
You don't need a reference to the Derived class. Your class is deriving from a template parameter. Just use the common method.
#include <iostream>
template <class T>
class Base : public T
{
public:
bool operator!() const
{
return !this->isOk();
}
};
class TemplateClass
{
public:
bool isOk() const
{
return true;
}
};
int main (int argc, char* argv[])
{
Base<TemplateClass> myClass;
if (!!myClass)
{
std::cout << "ok" << std::endl;
}
else
{
std::cout << "not ok" << std::endl;
}
return 0;
}
You can even use template specialization if you know ahead of time of derived classes that don't implement a common bool check.