2013-10-25 17 views
17

Chcę napisać klasę kontenera. Ten kontener ma metodę wstawiania, która ma dwie specjalizacje - najpierw używa konstruktorów kopiujących do kopiowania danych z jednego kontenera do innego elementu kontenera. Jeśli konstruktor kopiowania zgłasza wyjątek, po prostu cofam wszystkie zmiany w kontenerze, tak jak nic się nie dzieje.Wyjątek bezpieczny kod i semantyka ruchu

Druga specjalizacja wykorzystuje konstruktor ruchu i to jest miejsce, w którym rzeczy się komplikują. Gdy przenoszę elementy z jednego kontenera do innego elementu kontener po elemencie, konstruktor move może podać wyjątek. Jeśli tak się stanie - mam naprawdę brudny stan, gdy niektóre elementy są przenoszone, a inne elementy pozostają w jego oryginalnych miejscach. Jeśli spróbuję przenieść elementy z powrotem - mogę uzyskać kolejny wyjątek.

Czy można napisać coś takiego w sposób bezpieczny lub wyjątkowy, a bezpieczeństwo i semantyka wzajemnie się wykluczają?

Odpowiedz

22

Podczas pisania kodu wrażliwego na wyjątek należy używać std::move_if_noexcept, ale nadal należy korzystać z semantyki przeniesienia, gdy jest ona bezpieczna podczas kompilacji.

Więcej informacji na ten temat można znaleźć w sekcji Scott Meyers' talk at GoingNative 2013.

PS: O tak, pls pamiętaj, że jeśli twoje rzeczy nie są kopiowalne, przeniesiesz je bez względu na rzut/brak konstruktora ruchu.

+0

Nie otrzymuję "PS". Czy mógłbyś rozwinąć? –

+1

Jeśli twój ruch może rzucić, std :: move_if_noexcept fallbacks to copy. ALE! jeśli twoje rzeczy nie mają konstruktora kopiowania, std :: move_if_noexcept mówi "Meh" i przenosi go (co jeszcze może zrobić naprawdę?), prawdopodobnie otrzymując wyjątek i pozostawiając swój kontener w naprawdę złym stanie. –

+2

Straszny wybór, aby zdefiniować w ten sposób IMO ... możesz stworzyć własną wersję (bez wartości '&& std :: is_copy_constructible ::), która spowoduje błąd czasu kompilacji. – Joe

1

Korzystanie z delegowania konstruktora jest jednym ze sposobów, aby to zrobić. Jeśli nie-delegujący konstruktor (prawdopodobnie bez argumentów, ustawienie członków na wartości domyślne) zakończył pracę, a konstruktor delegował rzut, standard mówi, że twój lokalny stan został usunięty. W ten sposób nie możesz przeciekać. Nauczyłem się tego właśnie dzisiaj w this talk.

Przy okazji: jaki rodzaj kontenera wdrażasz, że STL jeszcze nie skonfigurował?

+0

Tablica hash z kukułką :) – Lazin

+0

nigdy o tym nie słyszałem, ale brzmi interesująco, jeśli [Wikipedia] (http://en.wikipedia.org/wiki/Cuckoo_hashing) wyjaśnia to^^ – HaMster

Powiązane problemy