When is `this` a valid and fully-formed pointer?

When is this a valid and fully-formed pointer for proper usage in a constructor member initializer list?

Consider:

1
2
3
4
5
6
7
8
9
10
class Parent
{
public:
  Parent() : m_beforeStuff{1}, m_child{[this](){callback();}}, m_afterStuff{5} { }
private:
  int m_beforeStuff;
  Child m_child;
  int m_afterStuff;
  void callback();
};


1
2
3
4
5
class Child
{
public:
  Child(std::function<void()> cb); // Store cb, call later.
};


(Sorry for any typos in this program, it's a hastily typed illustration).

In this scenario, I'm passing Parent's this to Child, but I'd assume that Parent's this pointer isn't fully valid until after its constructor completes. Could I use m_afterStuff in the callback, even tho the initializer list didn't get there yet?
Could I use m_afterStuff in the m_child() initialization, even though the initializer list didn't get there yet?

Using it in the callback is a bit more straightforward, since the value should be assigned and valid at the point that the callback is called.
Last edited on
it's a hastily typed illustration

Why? Don’t we deserve a full fledged question?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <functional>
#include <iostream>


class Child {
public:
    std::function<void()> cb;

    Child(std::function<void()>);
};


Child::Child(std::function<void()> cb_arg)
    : cb { cb_arg }
{
}


class Parent {
public:
    Parent();

    void invokeCb();

private:
      int m_beforeStuff;
      Child m_child;
      int m_afterStuff;

      void callback();
};


Parent::Parent()
    : m_beforeStuff { 1 }
    , m_child { [this]() { callback(); } }
    , m_afterStuff { 5 }
{
}


void Parent::callback()
{
    std::cout << "Parent::callback(): m_afterStuff is " << m_afterStuff << ".\n";
}


void Parent::invokeCb()
{
    m_child.cb();
}


int main()
{
    Parent dad;
    dad.invokeCb();
}


Output:
Parent::callback(): m_afterStuff is 5.


Naming ‘Parent’ and ‘Child’ classes which don’t inherit one from the other just add contortions to a (probably pointlessly) convoluted code.
Seriously? Stop with the masturbatory responses to indulge your sense of superiority, for the love of God. Is it really that hard to just say, "Hey, here's the answer to your question" without all of the backhanded nonsense?

Why? Don’t we deserve a full fledged question?

Because that's all I had time for. If you don't like it, don't answer the question. Nobody is forcing you to read my, apparently, offensive code.

Naming ‘Parent’ and ‘Child’ classes which don’t inherit one from the other just add contortions to a (probably pointlessly) convoluted code.

It's literally 15 lines of code. Sorry to absolutely baffle you!
Seriously? Bad mouthing people trying to help is ridiculous, get over yourself. The example you gave is half baked so all you deserve is a half baked answer.

half baked answer
.

So we agree. Great. Question solved.
@Aaron Vienneau, I’m not the one who reported your posts, anyway.
In general, the this pointer doesn't point to an object that is valid or fully-formed until the initialization of the object is complete (all the necessary constructors have completed).

Until that point, the lifetime of the object pointed to by this has not yet begun.

Within the constructor, however, we may take advantage of the fact that some subobjects are already within their lifetime, and use the this pointer (and only the this pointer) to access those subobjects:
you can access any base class subobjects that are within their lifetime;
if a member subobject is already initialized, you can access it.

However, virtual member functions are statically dispatched inside the constructor,
Member functions inside the class may rely on an invariant that isn't yet established,
And you may not access sub-objects that are not initialized.

Could I use m_afterStuff in the callback

Yes, but you can not invoke the callback until m_afterStuff is initialized. Note that a lambda capture of [this] captures the current object by reference.
Last edited on
@Mbozzi

Thank you! I appreciate the detailed answer!

Topic archived. No new replies allowed.