Domanda

Ci sono molti svantaggi nell'uso di void * in C (relativi alla memoria, al tipo, all'efficienza ...). Nonostante ciò li usiamo molto per la flessibilità che offrono.

Elenca gli svantaggi / svantaggi usando void * (e la soluzione preferita in C - se possibile).

Modifica si prega di passare attraverso il seguente link: http: / /attractivechaos.wordpress.com/2008/10/02/using-void-in-generic-c-programming-may-be-inefficient/

È stato utile?

Soluzione

Non ci sono problemi di efficienza con i puntatori vuoti. Le uniche limitazioni con puntatori vuoti sono:

  • non è possibile riconoscere il puntatore del vuoto per ovvi motivi
  • sizeof (void) è illegale
  • non è possibile eseguire l'aritmetica dei puntatori su puntatori vuoti

Tuttavia GCC presume che sizeof (void) sia 1 e consenta l'aritmetica dei puntatori su puntatori vuoti - vedi qui

Altri suggerimenti

Non sono d'accordo con la premessa della domanda. Usiamo void * in C perché è l'unico modo per ottenere il polimorfismo. Esempio: funzioni di libreria qsort e bsearch. C'è solo un inconveniente: il polimorfismo basato sul vuoto * non è sicuro: una volta che si lancia un puntatore su vuoto *, non c'è nulla che ti impedisca di lanciare quel vuoto * sul tipo di puntatore sbagliato da sbaglio. I miei studenti commettono spesso questo errore.

Può esserci un costo in termini di efficienza perché a volte è necessario allocare spazio heap per utilizzare una struttura di dati polimorfici.

Chiunque desideri vedere i vantaggi e gli svantaggi nell'uso di strutture di dati polimorfici con vuoto * dovrebbe ottenere una copia del libro di Dave Hanson C Interfacce e implementazioni

Uh ... Non sono sicuro che ce ne siano così tanti. Ovviamente, non dovresti mai usare void * quando non è necessario. Se è possibile utilizzare un tipo ben definito, quindi farlo.

Nella mia esperienza, void * è il migliore per " anonimo " puntatori (che shock!), come nel valore di ritorno di malloc () e quando si tratta solo di buffer di bit opachi. Spesso, vuoi indirizzare questi buffer ad es. il livello di byte, quindi useresti unsigned char * , ovviamente.

L'uso casuale di void * in modo casuale laddove è necessario un puntatore sarebbe semplicemente un codice maleodorante e puzzolente, e ovviamente da evitare.

Il post collegato a confronta le operazioni con i puntatori vuoti con le operazioni con modelli C ++ e conclude che i modelli sono più efficienti. Questa non è certo una sorpresa, e il codice C ++ che ho visto usa puntatori vuoti raramente o mai. In genere non offre alcun vantaggio rispetto ad altre strutture C ++ e può essere un buco nel sistema di tipi.

Tuttavia, C non ha modelli in stile C ++ e sono necessari puntatori vuoti per implementare funzionalità che devono essere indipendenti dal tipo di dati.

Pertanto, quando scrivi in ??C, e hai bisogno di genericità, i puntatori vuoti sono il mezzo più efficiente per ottenerlo (poiché sono gli unici mezzi). Quando scrivi in ??C ++, ci sono modi migliori per fare quasi tutto ciò che i puntatori vuoti possono realizzare, quindi non usarli.

Il tuo link indicato, è parzialmente vero. Soprattutto, quando non si ha a che fare con oggetti (strutture) o, in generale, con tipi che non sono già stati allocati. L'uso di tipi nativi come ints, double, ecc. E void-pointers (ad esempio per un container) è quasi sempre una faccenda icky, perché hai la scelta di lanciare int (per un doppio non funziona) su un puntatore o devi allocare memoria aggiuntiva per il tipo di dati.

La prima scelta è sbagliata perché non è portatile, forse gli 0 non sono ammessi come valore e semplicemente si sente male. La seconda scelta spreca memoria ed è davvero un (enorme) rallentamento a causa delle allocazioni extra.

Ma nella maggior parte dei casi non hai a che fare con tipi nativi, ma con oggetti, meglio dire con puntatori a oggetti che sono già allocati, almeno lo faccio. Non ho mai avuto bisogno di una tabella hash o di una mappa per numeri interi o doppi. E avere implementazioni di container diverse solo per la sicurezza del tipo di puntatori mi sembra sbagliato, perché ogni implementazione aumenterà la tua dimensione binaria. Quindi, se hai solo bisogno di un contenitore per memorizzare i tuoi puntatori, non ci sono rallentamenti o sprechi di memoria nell'uso dei puntatori void.

Ma tieni presente che si trattava di implementazioni di container, come nell'articolo del blog che hai citato. In generale ci sono molte cose che non puoi realizzare senza usare i puntatori di vuoto.

Non so, ho trovato che i puntatori di vuoto sono piuttosto efficaci per accedere a diversi livelli di astrazione (ABC). Come mezzo per navigare tra classi interconnesse a diversi livelli di astrazione. È così semplice, è fantastico. Come la formula per e o il rapporto aureo, dovrebbe esserci un occulto che adora il vuoto * è fantastico :)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top