unique_ptr <0 LUB co robi mniej niż operator?


9

Mam do czynienia z kodem, który nie został napisany przeze mnie. Mam to oświadczenie:

// p is type of std::unique_ptr<uint8_t[]>
if (p < 0) { /* throw an exception */ }

Co więc p < 0oznacza w tym kontekście?
Na stronie z dokumentacją uważam, że mój przypadek dotyczy tego 16) y < nullptr, gdzie 0jest nullptr.

Ale co to robi?


1
W oparciu o fakt, że w x64 wskaźniki kanoniczne w zakresie jądra mają ustawiony górny bit, może to być (głupi, zakodowany na stałe) sposób sprawdzenia, czy wskaźnik należy do przestrzeni jądra - jeśli odpowiedź poniżej jest prawidłowa, to nie .
Michael Chourdakis

1
W WINAPI p==-1jest niepoprawny uchwyt. Ponieważ 2^64jest to absurdalnie duża liczba, każdy rozsądny pjest zawsze pozytywny. p<0Sprawdza więc nieprawidłowy uchwyt WINAPI. To nie jest dobry kod.
ALX23z

@OP: Czy możesz wyjaśnić nieco, w jakim kontekście ten kod jest używany? Czy jest używany w systemie Linux lub Windows? Czy wartość wskaźnika jest związana z jakimś kodem WINAPI? Myślę, że jeśli to wyjaśnisz, powyższe komentarze mogą być dobrą odpowiedzią.
orzech

@ ALX23z Ale czy uchwyt WINAPI powinien być typu uint8_t*(a nawet tablicy uint8_t)? Myślę, że są void*, prawda?
orzech

@ orzech nie są, nie void*mają makra HANDLE_PTR lub coś, co jest w zasadzie long*iirc.
ALX23z

Odpowiedzi:


2

unique_ptr <0 LUB co robi mniej niż operator?

Odpowiada przeciążeniu (11) na preferencjach cp operator<(const unique_ptr&, nullptr_t);. 0 domyślnie konwertuje na std::nullptr_t. Zgodnie z dokumentacją wynik jest następujący std::less<unique_ptr<T,D>::pointer>()(x.get(), nullptr).

Wynikiem jest implementacja zdefiniowana, ale bezwarunkowo fałszywa w prawdopodobnie większości systemów. Prawdopodobnie w egzotycznym systemie, w którym null nie ma binarnej reprezentacji 0, wynik może być prawdziwy.

Myślę, że moja sprawa to 16)

(16) jest taka sama odwrót: 0 > unique_ptr. Wynik jest taki sam.


Ale jest 0brany nullptrpod uwagę przez kompilator? Myślę, że to właśnie on się zastanawia. Przynajmniej dla mnie to nie ma sensu.
alteredinstance

@alteredinstance 0 nie jest „brany pod uwagę” nullptr(lub zależy od tego, co rozumiesz przez rozważanie). 0 domyślnie konwertuje na std::nullptr_t.
eerorika

Tak założyłem. Zastanawiam się, czy jest jakaś dokumentacja na temat niejawnej konwersji 0na nullptr, ponieważ widziałem tylko te dwie kompatybilne z porównaniami boolowskimi. Są porównywalne, ale miałem wrażenie, że nie można ich zamienić.
alteredinstance

@alteredinstance Konwersja nie odbywa się na odwrót. int x = nullptrjest źle sformowany.
eerorika

2
@alteredinstance std::nullptr_tzostał zaprojektowany do pracy z dowolną stałą zerową wskaźnika; nie tylko nullptr. 0 (na przykład 0L) są stałymi wskaźnikami zerowymi, więc intencją jest, aby można je było użyć do utworzenia std::nullptr_t.
eerorika

2

Sprawdź, operator <czy nie jest przeciążony gdzieś w bazie kodu. To chyba jedyny sposób, w jaki (p < 0)może być true.

Przykład:

bool operator< (const std::unique_ptr<uint8_t[]>&, int) { return true; }

int main() {
    std::unique_ptr<uint8_t[]> p;
    std::cout << (p < 0) << std::endl;
}

Wydruki:

1

demo na żywo

W przeciwnym razie, jak powiedzieli inni, 0niejawnie konwertuje na std::nullptr_t, który wybierze bool operator<(const unique_ptr<T, D>& x, nullptr_t)przeciążenie, które wywoła, std::less(p, 0)które zwróci false(nawet w systemie Windows z -1wartością wskaźnika).


To niekoniecznie powraca false. Jest to albo implementacja zdefiniowana, albo nieokreślona (nie jestem pewien.) Ale zgadzam się, że prawdopodobnie wróci falsedo większości (wszystkich?) Implementacji. Zobacz także odpowiedź @eerorika
orzech

0

To wyrażenie pasuje do tego operatora szablonu (0 jest konwertowane na nullptr):

template <class T, class D>
bool operator<(const unique_ptr<T, D>& x, nullptr_t);

Zwraca std::less<unique_ptr<T,D>::pointer>()(p.get(), nullptr)to zawsze fałsz (podobnie jak std::lessfunktor ścisłego rzędu) ( demo ).


Nie zawsze wraca false. To, czy tak jest, jest zdefiniowane w implementacji lub nieokreślone. Prawdopodobnie zawsze powraca falsew przypadku większości (wszystkich?) Bieżących implementacji.
orzech

@walnut O ile pytanie nie zawiera wyraźnego pytania o to, co mówi Standard (na przykład poprzez tag prawnika językowego ), próbuję odpowiedzieć z praktycznego punktu widzenia. Wszystkie praktyczne wdrożenie std::lesszwrotu false.
YSC

To dobrze, po prostu nie znalazłem przekonania („ ponieważ std :: less jest funktorem ścisłego porządku ”). Może to być ścisłe zamówienie bez zwrotu false. Praktycznym powodem byłoby to, że zerowa wartość wskaźnika jest reprezentowana przez najniższy możliwy adres lub coś wzdłuż tych linii.
orzech
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.