Salta al contenuto
Note per Studenti Esercizio - Quiz su conversioni, constexpr, free store e downcasting (terzo appello 2021-22, quiz)

Esercizio - Quiz su conversioni, constexpr, free store e downcasting (terzo appello 2021-22, quiz)

Esame

Quiz del terzo appello del corso di Laboratorio di Programmazione, Ing. Informatica UniPD, a.a. 2021-22 (30 giugno 2022, 90 minuti): dieci domande a quattro affermazioni vero/falso (giusta +1+1, sbagliata −0.25-0.25, non data 00). Gli altri esercizi dell'appello: Esercizio - Helper function e la classe Book (terzo appello 2021-22, teoria), Esercizio - Confronto tra list e vector (terzo appello 2021-22, teoria), Esercizio - Costruttore di default, di copia e di spostamento (terzo appello 2021-22, teoria), Esercizio - Gerarchia MyPointer, MyUniquePointer e MySharedPointer (terzo appello 2021-22, programmazione).

1) La conversione di una variabile da int a bool:

affermazione V/F motivo
È una conversione sicura F int →\to bool è nell'elenco delle conversioni non sicure (si perde l'informazione: ogni valore non nullo diventa true)
È una conversione non sicura V narrowing: int →\to bool
È una conversione non sicura solo su architetture ARM F non dipende dall'architettura
È una conversione sicura solo su architetture a 64 bit F idem: la sicurezza dipende dai tipi, non dal processore. Vedi C++ - tipi, variabili, espressioni e dichiarazioniun tipo definisce contenuto, intervallo di valori e operazioni; un oggetto è una regione di memoria con un tipo, il valore è la configurazione di bit letta in base al tipo, una variabile è un oggetto con un nome; inizializzazione (dare il primo valore) e assegnamento (cambiare il valore) sono diversi; le conversioni verso un tipo più capiente sono sicure, quelle verso un tipo meno capiente (narrowing, double->int, int->char) non lo sono e il compilatore le segnala di rado, ma la notazione con graffe {} le vieta; un'espressione calcola un valore da operandi e operatori, un lvalue è ciò che può stare a sinistra di =, constexpr vuole un valore noto in compilazione mentre const solo un valore che non cambia; gli operatori con side effect (++, --, +=) non vanno mischiati con altri usi della stessa variabile nella stessa espressione perché l'ordine di valutazione non è definito; una dichiarazione introduce un nome e un tipo, una definizione fornisce anche l'entità (memoria per una variabile, corpo per una funzione).C++ - tipi, variabili, espressioni e dichiarazioni →

2) In C++11, l'istruzione float x {3};:

affermazione V/F motivo
Dà errore in fase di compilazione in quanto 3 non è rappresentato in forma decimale F il literal intero 3 si converte a float esattamente: nessun narrowing
Inizializza la variabile x con il valore 3 V x == 3.0f
Crea un array (C-style) di lunghezza 3 F le graffe qui sono l'inizializzatore, non la dimensione
Dà errore in fase di compilazione se il codice prevede un cambio di valore della variabile x F x non è const: si può cambiare

3) In C++11, le keyword constexpr e const:

affermazione V/F motivo
Sono equivalenti F constexpr richiede un valore noto in compilazione
Rappresentano una variabile il cui valore costante è noto a tempo di compilazione per constexpr oppure al tempo di esecuzione per const V è la definizione
Indicano che una variabile è costante e quindi non è possibile cambiarne il valore V entrambe
Indicano che una variabile è costante ma nel caso di constexpr può cambiare durante l'esecuzione F una constexpr non cambia mai

4) Il passaggio di una variabile per riferimento a una funzione:

affermazione V/F motivo
Si ottiene precedendo il nome della variabile con il simbolo & V nella dichiarazione del parametro: void f(int& x). Nella chiamata il & davanti a una variabile è invece l'indirizzo
Permette di evitare la copia della variabile nello scope della funzione V il parametro è un alias
Permette l'accesso alla variabile in lettura e scrittura all'interno della funzione V salvo la const reference
È equivalente ad anteporre il simbolo * al nome della variabile F il puntatore è un'altra cosa: può essere nullo, si sposta, va dereferenziato. Vedi C++ - funzioni, reference e passaggio dei parametriuna funzione ha parametri formali (0 o più, input) e un valore di ritorno (0 o 1, output); in C++ gli argomenti si passano per valore, cioè il parametro è una variabile locale inizializzata con una copia dell'argomento, e modificarla non cambia l'originale; per oggetti grandi (vector, immagini) la copia costa, e si passa per reference (T&), un alias dell'oggetto del chiamante che permette lettura e scrittura, oppure per const reference (const T&), alias in sola lettura verificata dal compilatore, che accetta anche literal (oggetto temporaneo); regola: valore per oggetti piccoli, const T& per grandi da non modificare, T& solo se la funzione deve davvero modificare o produrre più di un output; il passaggio converte l'argomento nel tipo del parametro come in un'inizializzazione e un cast esplicito (static_cast) rende visibile l'intenzione.C++ - funzioni, reference e passaggio dei parametri →

5) In C++, una classe:

affermazione V/F motivo
Deve per forza avere almeno un dato membro e una funzione membro F può essere vuota (class Invalid {};)
Deve per forza avere un costruttore e un distruttore implementati dal programmatore F il compilatore li genera
In nessun caso può avere l'implementazione di una classe annidata nel suo corpo F le classi annidate sono lecite (Date::Invalid)
Una volta istanziata permette l'accesso ai dati membri solamente tramite l'operatore -> F . per gli oggetti, -> per i puntatori (e solo per i membri pubblici). Vedi C++ - classi, membri e invariantiuna classe è un tipo definito dal programmatore che rappresenta un concetto con una rappresentazione (dati membro) e delle operazioni (funzioni membro); l'interfaccia pubblica separa chi usa la classe da chi la implementa e i dati privati sono modificabili solo tramite l'interfaccia; struct è una class con membri pubblici di default; l'invariante è la regola che definisce gli stati validi, e il costruttore deve stabilirlo e ogni funzione membro conservarlo; il costruttore (stesso nome della classe) inizializza con una lista di inizializzazione e, se i dati non sono validi, lancia un'eccezione, l'unico modo per far fallire un costruttore; le funzioni membro si definiscono fuori dalla classe (solo le brevissime dentro, dove sono inline); le funzioni che non modificano l'oggetto sono dichiarate const; le funzioni che si possono scrivere con la sola interfaccia pubblica (operator==, next_sunday) sono helper function esterne, spesso nello stesso namespace.C++ - classi, membri e invarianti →

6) I record di attivazione (RA):

7) Il free store:

affermazione V/F motivo
Rappresenta un'area di memoria utilizzata per le variabili globali/locali di un programma F quelle stanno nei dati e nello stack
È accessibile utilizzando new e i puntatori V new restituisce un puntatore
Rappresenta un'area di memoria utilizzata durante l'allocazione dinamica della memoria V è l'heap
Deve essere deallocata al termine dell'esecuzione per evitare fenomeni di memory leak V intesa come: la memoria allocata dinamicamente va rilasciata con delete/delete[] (altrimenti leak); non si dealloca il free store nel suo insieme. Vedi C++ - allocazione dinamica della memoria con new e deletela memoria dinamica si prende dal free store (heap) con new, che restituisce un puntatore all'oggetto o al primo elemento dell'array (new T, new T[n], con inizializzatori {}), e si restituisce con delete (per new) e delete[] (per new[]); il puntatore non sa quanti elementi ci sono, la memoria non ha nome e non ha controllo dei limiti; in C++ non c'è garbage collector (scelta per efficienza e controllo), quindi un'area che perde ogni riferimento diventa garbage e produce un memory leak, e gli errori tipici sono la doppia cancellazione e il dangling pointer (si mette il puntatore a nullptr dopo delete); il distruttore ~T() è chiamato dal compilatore quando l'oggetto esce dallo scope o con delete e libera le risorse, per cui una classe come vector acquisisce la memoria nel costruttore e la rilascia nel distruttore; new alloca e chiama il costruttore, delete chiama il distruttore e libera; operator[] con due versioni (T& e const) dà accesso in lettura e scrittura al buffer; si alloca dinamicamente solo se serve davvero (memoria grande, dimensione nota a run-time, durata controllata).C++ - allocazione dinamica della memoria con new e delete →

8) I tipi che implementano una deep copy:

affermazione V/F motivo
Copiano solo i puntatori e le reference, senza copiare i dati F è la shallow copy
Devono definire in modo esplicito il costruttore di copia e l'assegnamento in caso utilizzino una allocazione dinamica della memoria V quelli generati copierebbero il puntatore
Permettono la copia dei soli membri privati della classe F si copia tutto lo stato
Hanno un tempo di esecuzione più lento rispetto ai tipi che implementano la shallow copy V si duplicano i dati

9) Il polimorfismo dinamico in C++:

10) Il downcasting in C++:

affermazione V/F motivo
Rappresenta la conversione di una classe derivata in una classe base F è l'upcasting (sempre lecito, senza cast); il downcasting va dalla base alla derivata
È l'unico cast che effettua verifiche a run-time V dynamic_cast
Viene effettuato tramite il dynamic_cast V
Funziona con puntatori e reference V puntatori: nullptr se non lecito; reference: eccezione bad_cast

Versione ripasso

Teoria collegata