2015-10-15 13 views
50

Nella mia GUI ho un widget che visualizza i grafici. Se ho più di un grafico ci sarà una legenda mostrata in un rettangolo sulla GUI.Posso moltiplicare un int con un booleano in C++?

Ho un QStringlist (legendText) che contiene il testo della legenda. Se non è richiesta una legenda, legendText sarebbe vuoto. Se ci sarà una legenda, legendText terrebbe il testo.

Per trovare l'altezza del rettangolo intorno alla leggenda vorrei fare quanto segue:

int height = 10; 
QStringList legendText; 
... 
height = height * (legendText->size() > 0); 
... 

Si tratta di una buona idea/buon stile di moltiplicare un int con un boolean? Avrò problemi con questo?

+2

Mi sembra che questa domanda è una questione di stile e la leggibilità, mentre il presunto preoccupazioni duplicati ottimizzazione. –

+5

Puoi, ma stai sacrificando la leggibilità. Preferirei rendere esplicito il mio intento. –

+0

Non mi è chiaro il motivo per cui si assegna 'height' in primo luogo, se si sta per annullarlo. Ciò confonde e ostacola anche la correttezza di 'const'. Perché non solo 'int const height = 10 * (legendText-> size()> 0);' oppure 'int const height = legendText-> isEmpty()? 0: 10; '(o una qualsiasi delle altre possibili variazioni)? –

risposta

107

Questo è tecnicamente valido, io un po 'poco chiaro.

Il bool sarà promossi ad un int, quindi il risultato è ben definito. Tuttavia, guardando quel codice, non ottengo immediatamente la semantica che stai cercando di ottenere.

Vorrei semplicemente scrivere qualcosa di simile:

height = legendText->isEmpty() ? 0 : height; 

Questo rende il vostro intento molto più chiara.

+8

Lo ridurrebbe ulteriormente a solo 'if (legendText-> empty()) height = 0;'. Questo è il solito modo di scrivere questo. – MSalters

32

E 'perfettamente secondo lo standard (§4.5/6):

Un prvalue di tipo bool può essere convertito in un prvalue di tipo int, con false diventare zero e true diventando uno.

Comunque, io suggerisco di usare isEmpty invece di confrontare size a zero height = height * (!legendText->isEmpty());

Oppure utilizzare l'operatore condizionale come le altre risposte suggeriscono (ma ancora con isEmpty invece di .size() > 0)

+0

Mi piace l'approccio senza rami della moltiplicazione per '! LegendText-> isEmpty()'. –

+0

@RandallCook Quale macchina, in particolare, stai ottimizzando? Le istruzioni di spostamento condizionale sono abbastanza comuni al giorno d'oggi, che rendono entrambe le opzioni senza branch. – hvd

16

È possibile utilizzare il operatore condizionale (ternario):

height = (legendText->size() >0) ? height : 0 ; 
11

Forse questo?

if(legendText->isEmpty()) 
{ 
    height = 0; 
} 

o

int height = legendText->isEmpty() ? 0 : 10; 
+4

Aggiungi 'const' a quello e sei d'oro. –

0

Alcune persone possono trovare seguenti informazioni utili (seguente codice dovrebbe essere considerata nei programmi ad alte prestazioni dove ogni materia ciclo di clock e il suo scopo è quello di mostrare tecniche alternative, mi wouldn' usarlo in questa particolare situazione).

Se è necessario codice veloce senza diramazioni è possibile implementare la moltiplicazione int con booleano utilizzando operatori bit a bit.

bool b = true; 
int number = 10; 
number = b*number; 

può essere ottimizzato per:

number = (-b & number); 

Se b è true poi -b è -1 e tutti i bit sono impostati a 1. Altrimenti tutti i bit sono 0.
NOT booleano (!b) può essere implementato da XOR'ing b con 1 (b^1).
Quindi nel tuo caso otteniamo seguente espressione:

height = (-(legendText->isEmpty()^1) & height); 
+1

Se hai bisogno di un codice veloce puoi * dire al tuo compilatore di ottimizzare il tuo codice *. Questo è ciò che fanno i compilatori. Il tuo codice fallirebbe su un sistema di complementi non 2. –

+0

I compilatori eseguono solo semplici ottimizzazioni. Non faranno il lavoro per te. Dovrebbero capire il codice e non siamo ancora arrivati. – Maciej

+0

"Il tuo codice fallirebbe su un sistema di complementi non 2". Tali sistemi sono molto rari ... – Maciej