2008-11-06 8 views
9

std::auto_ptr jest zepsute w VC++ 8 (którego używamy w pracy). Moim głównym zarzutem jest to, że pozwala na auto_ptr<T> x = new T();, co oczywiście prowadzi do strasznych awarii, a jednocześnie jest proste do zrobienia przez pomyłkę.Zastępowanie auto_ptr w VC++ 8

Z answer na inne pytanie tutaj na stackoverflow:

Należy zauważyć, że realizacja std :: auto_ptr w Visual Studio 2005 jest strasznie zepsuta. http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=98871 http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=101842

chcę użyć

  • boost::scoped_ptr, dla wskaźników, które nie powinny przechodzić na własność.
  • boost::shared_ptr, dla wskaźników w kontenerach i innych miejscach, w których są wymagane.
  • std::auto_ptr, dla wskaźników, które powinny/mogą przekazywać prawa własności.

Ale ponieważ std::auto_ptr jest podzielona na mnie, zastanawiam się, co byłoby najlepsze podejście:

  • Wymień std::auto_ptr coś z siatki. Podoba mi się to this jeden z Rani Sharoni (jeszcze go nie wypróbowałem).
  • Zamiast tego należy użyć boost::shared_ptr. Oczywiście, że będzie działać, chociaż będzie trochę drobne, o które mnie nie dbam. Ale chcę użyć auto_ptr, aby zasygnalizować zamiar wskaźnika. (Odpowiedz na głosowanie w sprawie tego podejścia, patrz: this).
  • Nigdy nie będę musiał przekazywać własności w praktyce, więc nie powinienem się o to martwić.

Aktualizacja: Oto co zrobiłem: skopiowane wspomnianą realizację auto_ptr przez Rani Sharoni. From here.

Czy drobne testy:

class T 
{ 
public: 
    T() { 
     OutputDebugStringA("T\n"); 
    }; 
    ~T() { 
     OutputDebugStringA("~T\n"); 
    }; 
}; 

{ 
    fix::auto_ptr<T> x(new T); // This just works. 
} 
{ 
    fix::auto_ptr<T> x = (new T); // Doesn't compile. Great! 
} 
{ 
    fix::auto_ptr<T> x = fix::auto_ptr<T>(new T); // Transfer of ownership works also. 
} 

Oczywiście te testy są w żaden sposób wyczerpujący i nie należy im ufać. Wdrożenie bezpiecznej dla wyjątków klasy szablonowej jest włochatym biznesem. Przynajmniej to działa lepiej niż wbudowane.

Uwaga: Nie wiem, czy mogę używać tej wersji jeszcze w odniesieniu do praw autorskich. Wysłałem e-mail do Rani i czekam na odpowiedź. Zaktualizuję ten wpis, gdy dowiem się więcej. Pozwolenie jest przyznawane każdemu, aby mógł użyć implementacji auto_ptr Rani Sharoni.

Dziękuję za wszystkie odpowiedzi.

+0

Podawanie własności nie jest czymś, co zdarza się często, ale zapewnia staranny sposób samodzielnej dokumentacji w ramach kodu. –

+0

To jest dokładnie moja myśl. Uwielbiam autodokumentowanie kodu. –

Odpowiedz

7

Przenieś do pobudzenia inteligentne kursory.

W międzyczasie możesz wyodrębnić działającą implementację auto_ptr ze starego/innego STL, więc masz działający kod.

Wierzę, że semantyka auto_ptr jest całkowicie zepsuta - zapisuje pisanie, ale interfejs w rzeczywistości nie jest prostszy: nadal musisz śledzić, która instancja jest obecnym właścicielem i upewnić się, że właściciel pozostawia ostatni.

unique-ptr "poprawki", które, poprzez wydanie wersji, nie tylko powodują rezygnację z własności, ale również ustawienie wartości RHS na wartość null. Jest to najbliższy zamiennik dla auto-ptr, ale z inną semantyką nie jest zamiennikiem typu drop-in.

Istnieje artykuł wprowadzający do boost smart pointers, autorstwa, ahem, mnie.

+0

Przeczytałem twój artykuł. Jest bardzo dobrze napisany. Dziękuję Ci. W większości przypadków wskaźniki doładowania będą w porządku. Nie jestem pewien, jak powinienem sobie poradzić z auto_ptr. Próbuję teraz ustanowić nową wytyczną dla inteligentnych wskaźników w pracy, więc lepiej zrozumiem to. –

+0

Er, 'auto_ptr' ustawia także wartość RHS na dowolną kopię. W ten sposób rezygnuje z własności! –

+0

IIRC niektóre (lub początkowe) implementacje nie. – peterchen

0

Użyj boost :: shared_ptr/boost :: scoped_ptr. Będzie to preferowany inteligentny wskaźnik w nadchodzących standardach C++ (jest już w TR1).

Edit: Proszę odnaleźć pokrewny dyskusja tutaj: Idiomatic use of std::auto_ptr or only use shared_ptr?

+0

Preferowane jest mocne słowo. shared_ptr i auto_ptr robią różne rzeczy. –

+0

Tak, to prawda: generalnie korzystałem z shared_ptr, ale może to wynikać z faktu, że nigdy nie miałem żadnego przypadku użycia dla auto_ptr. – MP24

+0

Już śledzę inne dyskusje na temat inteligentnego wskaźnika tutaj na stackoverflow, ale dziękuję jeszcze. Jestem już zdania, że ​​chciałbym używać auto, shared i scoped. Ale z powodu mojego kompilatora (i jego implementacji biblioteki), nie jestem pewien co robić. –

1

Dlaczego myślisz, że std :: auto_ptr <> jest uszkodzony.

Chciałbym jednak, że coś tak złego, jak to zostało zgłoszone do komitetu norm!

Czy to znaczy, że trzeba:

std::auto_ptr<T> x(new T); // Use the explicit constructor. 
+0

To nie jest zepsute wszędzie. Dokładnie w VC++ 8. VC++ 9 ma lepszą implementację. –

+2

Tak. Albo std :: auto_ptr x (nowe T); lub std :: auto_ptr x = std :: auto_ptr (nowe T); będzie działać. std :: auto_ptr x = nowy T; nie powinien się kompilować. Ma i wynik jest nieokreślony. –

+0

Co rozumiesz przez "wyniki są niezdefiniowane"? Czy nie powinien on domyślnie wywoływać konstruktora? Oczywiście nadal jest to (prawdopodobnie) wada. –

3

Czy można uznać za pomocą STLPort?

+0

Byłoby to zgodne z ideą "Zastąpienie koncepcji auto_ptr". Mam nadzieję, że mogę zrobić coś mniej niż wprowadzenie nowej implementacji STL w naszym projekcie. Ma dwa lata i piszemy to pięć osób. Ale i tak dzięki. –

+0

Techniczne zastąpienie implementacji STL "nie powinno" powodować żadnych problemów. Jeśli cokolwiek by to wtedy usunęło. Ale jeśli masz kod, który opiera się na tych problemach, to jesteś spieprzony. Biorąc pod uwagę, że jest to rozwiązanie typu "przeciągnij i upuść", być może warto zastanowić się, czy masz przepustowość do testowania? –

+0

Ja drugi. Zastąpienie STL powinno być prostą kwestią konfiguracji projektu do użycia STLPort (które, jak sądzę, wykorzystuje macierzysty STL, jeśli nie jest zepsuty). –

2

Użyj unique_ptr. Myślę, że zostały one wprowadzone jako lepsze auto_ptr.

http://www.boost.org/doc/libs/1_35_0/doc/html/interprocess/interprocess_smart_ptr.html#interprocess.interprocess_smart_ptr.unique_ptr

W rzeczywistości, ja skłonni uwierzyć auto_ptr może być zastąpiona nim:

http://objectmix.com/c/113487-std-auto_ptr-deprecated.html

+0

Boost ma jeden dostępny, chociaż nie jestem w 100% pewien, jakie wersje VC mają wystarczającą zgodność z normami językowymi, aby móc go wspierać. –

+0

Co więcej, dlaczego istnieje tylko boost :: interprocess :: unique_ptr i no boost :: unique_ptr. Chciałbym dowiedzieć się więcej przed podjęciem tej ścieżki. Standardowe propozycje dla unique_ptr wydają się działać tylko na bardzo zgodnych nowych kompilatorach (gcc). –

+0

Sądzę również, że wycofanie funkcji auto_ptr byłoby istotne tylko po zastąpieniu przez unique_ptr. –

0

O ile pamiętam, nie było go:

auto_ptr<T> x = auto_ptr<T>(new T()); ?? 
+1

To zbyt długo - 'auto_ptr x (nowa T())' zrobi to samo w mniej okrężny sposób. –

0

nie odpowiedź, ale na ogólnym interesie każdego, dla kogo te błędy są istotne. Jest one more related bug z VC8's auto_ptr, co ma związek z ukrytymi upcastami. Jest to prawdopodobnie najgorsze z tego grona, ponieważ inne błędy pozwalają po prostu skompilować kod, który w normalnych warunkach jest niezgodny z normami, ale przynajmniej kod zgodny działa dobrze. Z tym błędem kod, który jest zgodny z rzeczywistością, nie działa poprawnie.

Problem polega na tym. Standard określa konstruktory i operatory konwersji w taki sposób, że obsługują domyślne upcasting z auto_ptr s, tak jak w przypadku normalnych wskaźników. Jednak implementacja VC8 ma tam wartość reinterpret_cast, a nie static_cast. Oczywiście nie tylko to jest U.B. przez literę normy, ale zrywa również z wieloma klasami bazowymi i/lub wirtualnym dziedziczeniem. Oto przykład z kodeksu prawnego złamane przez to:

struct Base1 { int x; }; 
struct Base2 { int y; }; 
struct Derived : Base1, Base2 {}; 

std::auto_ptr<Derived> createDerived() 
{ 
    return std::auto_ptr<Derived>(new Derived); 
} 

std::auto_ptr<Base2> base2(createDerived()); 

Na jednym z moich ostatnich prac, kiedy wpadliśmy na ten problem w produkcji, skończyło się po prostu łatanie nagłówki siebie (jest to trywialne 2-liniowy fix) .