2015-05-20 22 views
10

Załóżmy, że chcę wywołać funkcję zewnętrzną mojego obiektu, aby wykonać pewne sprawdzenia wewnątrz konstruktora ciała. Ponieważ czas życia obiektu rozpoczyna się, gdy ciało wykonawcy kończy wykonywanie, czy jest to projekt niebezpieczny?C++: czas życia obiektu i funkcji zewnętrznych

struct A; 

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

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

To znaczy, ja dzwonię i funkcja zewnętrzna z nie-jeszcze-żywy obiekt. Czy jest to niezdefiniowane zachowanie?

Podobne pytania: jeśli umieściłem tę funkcję sprawdzającą jako funkcję składową (statyczną lub nie), co standard mówi o korzystaniu z obiektów nieżywych poza konstruktorem, ale wewnątrz klasy?

Czy istnieje jakaś różnica w koncepcji życiowej między punktem widzenia klasy i jej użytkowników (rodzaj życia w klasie a poza klasą)?

+2

[C++ FAQ] (https://isocpp.org/wiki/faq/ctors#using-this-inctors) ma informacje na ten temat. –

+0

Powinno być w porządku, o ile funkcja nie jest wirtualnym elementem i nie znajduje się na liście inicjującej. – KABoissonneault

+1

A const & jest odniesieniem i nie jest ani inicjowany na początku sprawdzania, ani niszczony na końcu funkcji. Poza tym w konstruktorze obiekt jest w pełni skonstruowany. Nie widzę żadnego problemu w tym kodzie – Brahim

Odpowiedz

8

Żywotność A nie zaczęły gdy check() jest nazywany, ponieważ w [base.life]

Żywotność obiektu typu T rozpoczyna się, gdy:

  • pamięci o uzyskuje się prawidłowe wyrównanie i rozmiar dla typu T i jeśli obiekt nie inicjuje inicjowania, jego inicjalizacja jest zakończona.

A ma inicjalizację inną niż próżnia. Jego zakończeniu inicjalizacji, gdy w [class.base.init]/13

W nie-delegowania konstruktora przechodzi inicjalizacji w następującej kolejności:

  • ...
  • - Na końcu jest wykonywane oświadczenie złożone złożenia konstruktora.

Pomimo A niemającym życia jeszcze rozpoczęta, średnia dodatkowo dostarcza, w [class.base.init]/16:

metody (w tym funkcji wirtualnej, 10,3) mogą być wywoływane dla obiektu w budowie ... Jednakże, jeśli te operacje są wykonywane w inicjatorze ctor (lub w funkcji zwanej bezpośrednio lub pośrednio od inicjatora ctor) przed wszystkimi pamięciami. inicjacja alizery dla klas bazowych zostały zakończone, wynik operacji jest niezdefiniowany.

W odniesieniu do kwestii życiowych, nie ma różnicy między:

void check(const A&) { .. } 
struct A { 
    A() { check(*this); } 
}; 

oraz:

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

Ten ostatni jest wyraźnie dozwolone przez (jak to nie jest w konstruktor-inicjatora), więc nie widzę powodu, aby wykluczyć tę pierwszą na podstawie życia.

+0

... chyba że A jest klasą podstawową z wirtualnymi elementami, które są wywoływane przez 'check()' - wtedy wyniki mogą Cię zaskoczyć. –

+0

@RichardHodges To nie jest niezdefiniowane zachowanie. – Barry

+0

@Barry Czy na pewno inicjalizacja się kończy? http://stackoverflow.com/a/20409911/1794803 –