Wiem, że to pytanie zostało już zadane kilka razy, ale nie mogłem znaleźć odpowiedzi na ten konkretny przypadek.
Powiedzmy, że mam trywialną klasę, która nie posiada żadnych zasobów i ma pusty destruktor i domyślny konstruktor. Ma garść zmiennych składowych z inicjalizacją w klasie; żaden z nich nie jest const
.
Chcę ponownie zainicjować i sprzeciwić się takiej klasie bez deInit
ręcznego pisania metody. Czy można to zrobić w ten sposób?
void A::deInit()
{
new (this)A{};
}
Nie widzę z tym żadnego problemu - obiekt jest zawsze w poprawnym stanie, this
wciąż wskazuje ten sam adres; ale to jest C ++, więc chcę być pewien.
c++
placement-new
Amomum
źródło
źródło
*this = A{};
?*this = A{};
oznacza,this->operator=(A{});
tj. Stwórz obiekt tymczasowy i przypisz go*this
, zastępując wartości wszystkich elementów danych wartościami tymczasowymi. Ponieważ tego właśnie chcesz i jest (moim zdaniem) bardziej czytelna niż nowe miejsce docelowe, wybrałbym to zamiast tego.Odpowiedzi:
O ile mi wiadomo, podobnie jak legalność
delete this
, nowe miejscethis
jest dozwolone. Ponadto, jeśli chodzi o tothis
, czy lub inne wcześniej istniejące wskaźniki / odniesienia mogą być później użyte, istnieje kilka ograniczeń:Pierwsze dwa są spełnione w tym przykładzie, ale dwa ostatnie będą musiały zostać wzięte pod uwagę.
W odniesieniu do trzeciego punktu, biorąc pod uwagę, że funkcja nie jest zakwalifikowana do const, należy całkiem bezpiecznie założyć, że oryginalny obiekt nie jest const. Błąd jest po stronie wywołującej, jeśli constness został odrzucony. Jeśli chodzi o członka const / referencyjnego, myślę, że można to sprawdzić, stwierdzając, że można to przypisać:
Oczywiście, ponieważ możliwość przypisania jest wymogiem, możesz po prostu użyć tego,
*this = {};
którego spodziewałbym się stworzyć ten sam program. Być może bardziej interesującym przypadkiem może być ponowne użycie pamięci*this
dla obiektu innego typu (co nie spełniłoby wymagań dotyczących używaniathis
, przynajmniej bez ponownej interpretacji + prania).Podobnie jak w przypadku
delete this
nowego miejsca docelowego zthis
trudem można je opisać jako „bezpieczne”.źródło
delete ptr
jestnew T()
. Odwrotnościąnew(ptr)T{}
jestptr->~T();
. stackoverflow.com/a/8918942/845092Reguły, które to obejmują, znajdują się w [basic.life] / 5
i [basic.life] / 8
Ponieważ twój obiekt jest trywialny, nie musisz się martwić o [basic.life] / 5 i dopóki spełniasz warunki punktorów z [basic.life] / 8, to jest bezpieczny.
źródło