Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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)?

like image 636
Peregring-lk Avatar asked May 20 '15 12:05

Peregring-lk


People also ask

What is the lifetime of a variable in C?

What is the Lifetime of a variable in C? Lifetime of a variable is defined as for how much time period a variable is occupying a valid space in the system's memory or lifetime is the period between when memory is allocated to hold the variable and when it is freed. Once the variable is out of scope its lifetime ends.

What is scope visibility and lifetime of variables in C?

Scope is about the 'availability' of the declared variable: within the same scope, it is not possible to declare/define two variables of the same type with the same name. Lifetime is about the duration in which the variable is 'alive': it determines how long the named or unnamed variable has memory allocated to it.

What is the lifetime of an object and how can you extend the lifetime of an object?

The lifetime of a temporary object may be extended by binding to a const lvalue reference or to an rvalue reference (since C++11), see reference initialization for details.

What is the lifetime of an object?

In object-oriented programming (OOP), the object lifetime (or life cycle) of an object is the time between an object's creation and its destruction.


1 Answers

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.

like image 71
Barry Avatar answered Oct 22 '22 16:10

Barry