6

Bjarne sugeruje użycie warunku, jeśli jest jako ograniczenie zakresu. W szczególności ten przykład.Podwójnie jako prawda/fałsz

if (double d = fd() ) { 
    // d in scope here... 
} 

Jestem ciekawostką, jak interpretować deklarację w sposób prawdziwy/fałszywy.

  1. Jest to deklaracja
  2. Jest to podwójnie.

Edytuj: Jest w wersji 6.3.2.1 Język programowania C++ jako zalecenie.

Edit2: templatetypedefs sugestie wskaźników, w szczególności z dynamicznymi rzutami, mogą dać wgląd w sugestię Bjarnesa.

SteveJessop mówi mi: - Warunek nie jest wyrażeniem, ale może być także deklaracją, a wartość użyta jest wartością podlegającą ocenie.

+1

Odpowiedź na to pytanie (http://stackoverflow.com/q/9833790/636019) również odpowie na twoje pytanie. – ildjarn

+1

Właśnie przeczytałem sekcję, o której mówisz, i odniosłeś wrażenie, że dyskusja dotyczyła raczej wykorzystania go jako ograniczenia zakresu (i uzyskania dodatkowej korzyści z kompaktowego kodu) i nie miała wiele wspólnego z określony typ danych. Myślę, że mógłby zastąpić 'double' z' int' i nadal osiągnął zamierzony przekaz. Tak właśnie to czytałem. – jedwards

+0

@jedwards Tak, ale użycie podwójnego jest błaganiem o odpowiedź. Deklaracja int jest wciąż anomalią, która zasługuje na odpowiedź. –

Odpowiedz

6

Kod, który widzisz, jest wyspecjalizowaną techniką deklarowania zmiennych w instrukcjach if. Ty powszechnie zobaczyć coś takiego:

if (T* ptr = function()) { 
    /* ptr is non-NULL, do something with it here */ 
} else { 
    /* ptr is NULL, and moreover is out of scope and can't be used here. */ 
} 

Szczególnie częsty przypadek jest wykorzystanie dynamic_cast tutaj:

if (Derived* dPtr = dynamic_cast<Derived*>(basePtr)) { 
    /* basePtr really points at a Derived, so use dPtr as a pointer to it. */ 
} else { 
    /* basePtr doesn't point at a Derived, but we can't use dPtr here anyway. */ 
} 

Co dzieje się w Twoim przypadku jest to, że jesteś deklarowania double wewnątrz rachunku if. C++ automatycznie interpretuje dowolną niezerową wartość jako true i dowolną zerową wartość jako false. Co oznacza ten kod, to "zadeklaruj d i ustaw go na równy fd(). Jeśli jest niezerowy, wykonaj instrukcję if."

To jest bardzo zły pomysł, ponieważ double s są przedmiotem różnego rodzaju błędów zaokrąglania, które uniemożliwiają im w większości przypadków 0. Ten kod prawie na pewno wykona treść instrukcji if, chyba że function jest bardzo dobrze zachowany.

Mam nadzieję, że to pomoże!

+0

@CaptainGiraffe można oznaczyć jako odpowiedź ... – bames53

+0

@ bames53 To prawie tak, jakbyś czytał w moich myślach. Nadal chciałbym komentować niespójność bool b = double d = fd(); chociaż, ale to może być kolejne pytanie. –

+1

"i poza tym jest poza zakresem i nie może być tutaj użyta" - to jest * w * zakresie w klauzuli "else", ale oczywiście ze wskaźnikami i inteligentnymi wskaźnikami nie ma zbyt wiele, co można zrobić ze zmienną, która testuje false, więc normalnie nie widzisz, żeby tam był używany. Mógłbym przypisać inną wartość. Jeśli używałeś go z typem zdefiniowanym przez użytkownika, który ma bezpieczny idol, aby wskazać "niepowodzenie", to być może w klauzuli "else" przesłuchasz obiekt * dlaczego * to "zawiodło". –

2

Instrukcja if predykatuje na wartość przypisaną do zmiennej w wyrażeniu przydziału. Jeśli double ocenia wartość inną niż 0.0, uruchomi kod w środku.

Zauważ, że nie powinieneś porównywać podwójnych z zero, ale generalnie działa na moim doświadczeniu.

Zasadniczo nie powinieneś tego robić.

Inni autorzy tego tematu stwierdzili, że to wyrażenie jest używane do wykluczenia przypadku zerowego, aby uniknąć dzielenia przez zero. To zdecydowanie sprytne i taka sytuacja uzasadnia takie użycie, o ile mi wiadomo (ale weź pod uwagę nieporozumienie, jakie może spowodować ten kod).

+0

Bjarne mówi mi, że to idiom. Tylko mówię. 6.3.2.1 Język programowania C++. –

+2

Może on odnosić się do faktu, że podwójne 'd' jest * w zasięgu * wewnątrz (i tylko wewnątrz) bloku' if'. Co nie musi być oczywiste. Chodzi mi o to, że często nie ma dobrego powodu, aby rzucić podwójną do bool. Dlaczego zmienna typu 'int' nie jest używana, nie mam pojęcia. (TO jest bardzo popularny idiom) –

+2

Dlaczego na ziemi nie powinieneś porównywać podwójnych z zero? Działa idealnie dobrze i ma dobrze zdefiniowane zachowanie. Płynna matematyka może być zaskakująca, ale nie jest voodoo i nie jest dobrze obsługiwana przez tego typu porady. –

2

Jest to zarówno deklaracja, jak i kopia. Jest to odpowiednik tego modelu, ale jest on warty małej dodatkowej składni, aby uprościć, ponieważ jest dość użyteczny i powszechny.Ponadto transformacja jest mniej oczywista, gdy zaczniesz dodawać inne klauzule, ponieważ d jest poza ich zasięgiem.

Ponadto, jak inni to zauważyli, jest to przydatne w ogóle, ale typy FP w specyficzny mieć pewne problemy, gdy porównywane 0.

+0

To jest pierwsza odpowiedź, z której jestem zadowolony. Ta składnia jest wszędzie. – jedwards

+0

Moje pytanie dotyczy również bool b = podwójne d = 0,0; –

+1

Czy jesteś pewien, że 'd' jest poza zasięgiem gałęzi' else'? – jedwards

5

W przykładzie Stroustrup daje kod w bloku if dzieli wartości przez d:

if (double d = prim(true)) { 
    left /= d; 
    break; 
} 

dzielenie przez 0 jest niezdefiniowane zachowanie, więc to sprawia, że ​​jakiś sens w tym przypadku przetestowania d z wartością 0.0 przed podziałem. Umieszczenie definicji w warunku jest wygodnym sposobem na to, z powodów, które Stroustrup stwierdza.

Twój kod nie podaje powodu, dla którego wartość 0.0 byłaby wyjątkowa, a zatem nie jest jasne, dlaczego ktokolwiek łączyłby definicję d z tym testem. Używaj tylko wzorca Stroustrup, gdy wartości "fałszywe" zdefiniowanego typu muszą być traktowane specjalnie. W przeciwnym razie wykonaj to:

{ 
    double d = fd(); 
    // d in scope here... 
} 
+0

Po prostu przeczytałem sekcję i nie nawiązałem połączenia - myślałem, że to przykład odrzutowy - - dobry połów. Wszelki wgląd w 'break;'? – jedwards

+0

@jedwards: poza tym, co oczywiste (wyłamuje się z otaczającej pętli lub przełącznika, nie pokazane w tym fragmencie kodu) Nie wiem. Może ten fragment kodu pochodzi z jakiegoś kodu używanego gdzie indziej w rozdziale/książce? W tym przypadku nie wiem, co to jest funkcja 'prim'. –

+0

Aww, Miałem trochę nadziei, że to była jakaś sztuczka, która intryguje mnie jak niektóre z [tych klejnotów] (http://www2.research.att.com/~bs/bs_faq.html). Dzięki! – jedwards

Powiązane problemy