2012-05-16 12 views
5

codice dato simile al seguente:Un assegnamento letterale a int in C++ genera un'eccezione?

void f() 
{ 
    int i; 
    i = 0; 
} 

è possibile il sistema potrebbe generare un'eccezione a causa della semplice assegnazione?

[Modifica: Per quelli che dicono "Nessuna eccezione non può verificarsi", puoi indicarmi la direzione della parte dello standard C++ che dice questo? Non riesco a trovarlo.]

+6

è il tipo sempre 'int' e l'RHS sempre un valore letterale? O stai chiedendo del caso generale? (Anche quello che hai mostrato non era un incarico) – Flexo

+0

Grazie per aver catturato quel punto. Ho modificato l'esempio. Alla tua prima domanda, per entrambi, in realtà. –

risposta

7

Anche se probabilmente ti sarà difficile trovare una certezza nello standard, una semplice regola empirica è che tutto ciò che è legittimo in C probabilmente non può essere gettato. [Edit: Il più vicino che sono a conoscenza di una dichiarazione diretta in tal senso è al §15/2, che dice che:

codice che esegue un rimessa espressione è detto di “un'eccezione ;”[...]

Guardando che in senso inverso, il codice che non esegue una rimessa espressione non un'eccezione]

lanciare si limita principalmente a due possibilità:. la prima è invocando UB. Il secondo sta facendo qualcosa di unico per C++, come l'assegnazione ad un tipo definito dall'utente che sovraccarica lo operator =, o usando un'espressione new.

Modifica: Per quanto riguarda un compito, ci sono diversi modi in cui può essere lanciato. Ovviamente, lanciando l'operatore incaricato stesso lo farebbe, ma ci sono un buon numero di altri. Ad esempio, se il tipo di origine non corrisponde al tipo di destinazione, è possibile ottenere una conversione tramite un operatore di cast nell'origine o un costruttore nella destinazione, uno dei quali potrebbe generare.

+0

Le implementazioni sono libere di imporre limiti alle risorse, no? Se non sono "non più stack e nessun registro di riserva" (almeno teoricamente) è un valido motivo per lanciare e solo individuato al primo utilizzo? – Flexo

+0

In teoria si. VC++ 6 (per un esempio) ha fatto cose del genere - ma ha funzionato abbastanza male che VC++ non esiste più e sarei almeno un po 'sorpreso nel vedere qualcun altro provarlo in qualunque momento presto. –

+0

@JerryCoffin Per una definizione sufficientemente rigorosa di "legittimo in C". Assegnare un punto mobile a un int può comportare un comportamento indefinito, e un'eccezione è valida come qualsiasi altra cosa nel caso di comportamento non definito (sebbene forse non da un punto di vista della qualità dell'implementazione). –

0

se è solo uno int, quindi no - non getterà.

se è qualcosa di più complesso, come un vettore, può essere lanciato per una serie di motivi (ad esempio, errore di allocazione o alterazione da un thread secondario).

+0

Errore di allocazione definito per generare un'eccezione (a meno che non si stia utilizzando un allocatore personalizzato). L'accesso a un vettore da un altro thread mentre lo stai modificando è un comportamento indefinito e può succedere di tutto. Da un punto di vista della qualità dell'attuazione, tuttavia, non aspetterei un'eccezione. –

2

Può generare un'eccezione solo in un caso: in caso di sovraccarico di operator=() per questi due tipi; similare, quando è necessaria la conversione, anche il costruttore di conversione o operator T() può lanciare. Dipende dall'implementazione esatta quindi - per sapere se getterà, cerca informazioni su di esso nella documentazione della libreria che stai utilizzando.

6

C'è un sacco di cose che sembrano le assegnazioni che possono gettare un modo o nell'altro:

int operator"" _t(const char *) { throw 0; } // C++11 user defined literal 

struct foo { 
    foo(int) { throw 0; } 
    operator int() { throw 0; } 
    foo& operator=(int) { throw 0; } 
}; 

int main() { 
    int i; 
    i = 0; // can't throw 
    i = 0_t; // User defined literal throws 
    foo f = 0; // Constructor throws 
    i = f; // conversion operator throws 
    f = 0; // assignment throws 
    f = f; // both conversion and assignment would like to throw 
} 

(compreso il nuovo uno da C++ 11)

3

Se siete preoccupati assinging 0 (che ha il tipo) a int, §5.17 dello standard specifica esattamente la semantica dell'operazione di assegnazione e non ci sono casi in cui può verificarsi un'eccezione. Se si è interessati all'assegnazione di un'espressione arbitraria a , , §5.17 afferma che “ l'espressione viene convertita implicitamente nel tipo cv-non qualificato dell'operando di sinistra."A seconda del tipo effettivo dell'operando destra:

  • Se si tratta di un tipo integrale, se il valore istantaneo non può essere rappresentato in un int, i risultati sono attuazione definite (lo standard C è più esplicito: deve risultare in uno int con un valore definito dell'implementazione o un segnale definito implementazione)

  • Se è un valore in virgola mobile, il risultato è un comportamento non definito se il valore dopo il troncamento a zero non può essere rappresentato in un int, il comportamento non è definito (quindi potresti ricevere un'eccezione)

  • Se è un tipo definito dall'utente, verrà chiamato un operatore di conversione definito dall'utente. Quale può generare un'eccezione.

Se siete preoccupati per l'assegnazione di altri tipi: per ogni set di tipi non-classe, c'è un elenco di regole come sopra, ma le uniche possibili eccezioni sarà a causa di un digitare conversione. Per i tipi di classe , verrà utilizzato lo operator=. Quale può generare un'eccezione, a seconda di cosa contiene.