2016-03-17 36 views
10

Ten kod jest to, co chcę zrobić:Co dzieje się z unique_ptr po std :: move()?

Tony& Movie::addTony() 
{ 
    Tony *newTony = new Tony; 
    std::unique_ptr<Tony> tony(newTony); 
    attachActor(std::move(tony)); 
    return *newTony; 
} 

Zastanawiam się, czy mogę to zrobić w zamian:

Tony& Movie::addTony() 
{ 
    std::unique_ptr<Tony> tony(new Tony); 
    attachActor(std::move(tony)); 
    return *tony.get(); 
} 

Ale *tony.get() być ten sam wskaźnik lub null? Wiem, że mogłem zweryfikować, ale co jest standardem do zrobienia?

+0

Dlaczego jesteś 'move()' '' unique_ptr' na 'attachActor()' na początek? Co właściwie robi funkcja 'attachActor()'? –

Odpowiedz

15

Nie, nie możesz tego zrobić zamiast tego. Przeniesienie unique_ptr anuluje to. Jeśli nie, to nie będzie wyjątkowe. Ja oczywiście zakładając, że attachActor nie zrobić czegoś głupiego takiego:

attachActor(std::unique_ptr<Tony>&&) { 
    // take the unique_ptr by r-value reference, 
    // and then don't move from it, leaving the 
    // original intact 
} 

rozdział 20.8.1 ustęp 4.

Dodatkowo u (the unique_ptr obiektu) można, na życzenie, transfer własność na inny unikalny wskaźnik u2. Po zakończeniu takiego przeniesienia następujące postconditions przytrzymanie:
      - u2.p jest równa wstępnie przelać,
      - up jest równa nullptr i
      - jeśli stan wstępny transferu poprzedzony, taki stan został przeniesiony na u2.d.

+0

Mimo to prawdopodobnie nie jest dobrym pomysłem posiadanie funkcji, która w każdym razie bierze 'unique_ptr &&' (poza konstruktorem ruchu i przypisaniami ruchu). – Rufflewind

+0

@Rufflewind: Zgoda –

+0

@BenjaminLindley, dziękuję za odpowiedź! Tak, attachActor() przyjmuje std :: unique_ptr , nic nadzwyczajnego. – user3496846

7

Norma mówi (§   20.8.1.2.1 ¶   16, kursywa dodana), że konstruktor akcja std::unique_ptr

unique_ptr(unique_ptr&& u) noexcept; 

konstruuje unique_ptr przez przenoszącego własność z u do *this.

Dlatego po przeniesieniu-wybudować tymczasowy obiekt, który zostanie przekazany jako argument do attachActor formularzu tony, tony już nie jest właścicielem obiektu, a tym samym tony.get() == nullptr. (Jest to jeden z nielicznych przypadków, w których standardowa biblioteka rzeczywiście tworzy twierdzenia o stanie obiektu przeniesionego z zewnątrz).

Jednak chęć zwrócenia referencji może być spełniona bez uciekania się do nagiego new i surowego wskaźniki.

Tony& 
Movie::addTony() 
{ 
    auto tony = std::make_unique<Tony>(); 
    auto p = tony.get(); 
    attachActor(std::move(tony)); 
    return *p; 
} 

Kod ten zakłada, że ​​attachActor nie zrzuci swojego argumentu na podłogę. W przeciwnym razie wskaźnik p będzie zwisał po attachActor ma numer return. Jeśli nie można na nim polegać, musisz przeprojektować interfejs i zamiast tego używać wskaźników udostępnionych.

std::shared_ptr<Tony> 
Movie::addTony() 
{ 
    auto tony = std::make_shared<Tony>(); 
    attachActor(tony); 
    return tony; 
} 
+0

Przeniesienie własności nie oznacza, że ​​'u' nie posiada niczego, tylko że nie jest już właścicielem obiektu, który posiadał wcześniej. Jeśli byłby to jedyny wymóg, transfer mógłby się odbyć po prostu ** zamiana ** własności obiektu między 'u' i' * this' (co robią inne konstruktory ruchu, aby zapobiec alokacji i dezalokacji). Ale jak zauważa Benjamin Lindley, istnieją dodatkowe wymagania dotyczące std :: unique_ptr poza samym tekstem "przeniesienie własności". – Dreamer