Q:

C++: lifetime of an object and external functions

Let's suppose I want to call an external function of my object to perform some checks inside the body constructor. Since the lifetime of an object begins when the constructor's body finishes its execution, is it an unsafe design?
struct A;

void check(A const&) { /* */ }

struct A
{
    A() { check(*this); }
};

I mean, I'm calling and external function with a not-yet-alive object. Is it undefined behaviour?
Related questions: if I put that checking function as a member function (static or not), what does the standard says about using non-yet-alive objects outside the constructor but inside the class?
It there any difference in the lifetime concept between the point of view of a class and its users (a sort of in-class versus out-class lifetimes)?

A:

The lifetime of A will not have begun when check() is called because, from [base.life]:

The lifetime of an object of type T begins when:

storage with the proper alignment and size for type T is obtained, and
if the object has non-vacuous initialization, its initialization is complete.

A has non-vacuous initialization. Its initialization is complete when, from [class.base.init]/13:

In a non-delegating constructor, initialization proceeds in the following order:

...
— Finally, the compound-statement of the constructor body is executed.

However, despite A not having its lifetime begun yet, the standard additionally provides, in [class.base.init]/16:

Member functions (including virtual member functions, 10.3) can be called for an object under construction... However, if these operations are performed in a ctor-initializer (or in a function called directly
  or indirectly from a ctor-initializer) before all the mem-initializers for base classes have completed, the result of the operation is undefined.

With regards to lifetime issues, there's no difference between:
void check(const A& ) { .. }
struct A { 
    A() { check(*this); } 
};

And:
struct A {
    void check() const { .. }
    A() { check(); }
};

The latter is explicitly allowed for (as it's not in a ctor-initializer), so I see no reason to exclude the former on lifetime grounds. 

