2010-06-24 9 views
8

Cosa c'è di sbagliato in questo:wchar_t puntatore

wchar_t * t = new wchar_t; 

t = "Tony"; 

ho pensato che avrei potuto usare un puntatore wchar_t come stringa ...

+0

possibile duplicato di [Cosa c'è di sbagliato con questo codice ?] (http://stackoverflow.com/questions/3080137/what-is-wrong-with-this-code) o http://stackoverflow.com/questions/1577765/why-must-a-pointer-to- a-char-array-need-strcpy-to-assign-characters-to-its-array – bk1e

risposta

25

Il codice ha due problemi.

Primo, "Tony" è un puntatore a una stringa di char. L"Tony" è la stringa ampia appropriata.

In secondo luogo, si assegna un singolo wchar_t tramite nuovo, quindi si perde immediatamente traccia di esso riassegnando il puntatore a Tony. Ciò si traduce in una perdita di memoria.

+4

Per espandere la spiegazione di Michael, la sintassi corretta sarebbe 'wchar_t * t = L" Tony ";'. Questo dovrebbe dichiarare un puntatore e inizializzarlo in modo che punti alla stringa statica (ampia) "Tony". – bta

+3

La sintassi dovrebbe in realtà essere 'wchar_t const * t = L" Tony ";'. Per capire perché, si consideri la dichiarazione '* (t + 1) = L'i ';' – MSalters

-1

questo è completamente sbagliato. Non è necessario allocare due byte, fare in modo che puntino verso di essi e quindi sovrascrivere il puntatore t che perde la memoria persa per sempre.

Inoltre, "Tony" ha un tipo diverso. Usa:

wchar_t *t = L"Tony";

IMHO meglio non utilizzare wchars a tutti - Vedi https://stackoverflow.com/questions/1049947/should-utf-16-be-considered-harmful

+0

Probabilmente un errore di battitura, ma wchar_t t = ... dovrebbe essere wchar_t * t = ... –

+0

corretto, thx. a tpyo .. –

+4

Anche un wchar_t non è necessariamente due byte. Nella versione di gcc sto usando un wchar_t è 4 byte, e lo standard dice che è specifico del compilatore. Può anche essere un singolo byte. –

5

Ciò che è prima è assegnare un puntatore a un nuovo numero assegnato wchar_t a t, quindi provare ad assegnare una stringa non ampia a t.

È possibile utilizzare invece std::wstring? Questo gestirà tutte le tue esigenze di gestione della memoria per te.

+0

wstring esiste solo in MSVC. Non è standard. –

+6

@Pavel: È molto sbagliato. wstring è 'typedef''ed come' basic_string 'ed esiste su * ogni * sistema C++/toolchain compatibile. – rubenvb

+6

@Pavel: §21.2/2: "L'intestazione' 'definisce anche due classi template specifiche' stringa' e 'wstring' e le loro caratteristiche speciali." – GManNickG

0

è possibile, è solo che "Tony" è una stringa hardcoded, e sono ANSI di default nella maggior parte degli editor/compilatori. Se vuoi dire all'editor che stai digitando una stringa Unicode, quindi prefisso con L, ad es. t = L"Tony".

Hai altri problemi con il tuo codice, la tua allocazione sta allocando un singolo carattere Unicode (2 byte), quindi stai cercando di puntare la variabile originale sulla stringa costante, perdendo così quei 2 byte.

Se si desidera creare un buffer di dati e luogo Unicode i dati in esso, si vuole fare:

wchar_t* t = new wchar_t[500]; 
wcscpy(t, "Tony"); 
+0

La dimensione di un wchar_t è specifica del compilatore e può essere piccola come 1 byte e grande come 4. –

11

Un puntatore solo punta a un singolo valore. Questo è importante.

Tutto ciò che hai fatto è assegnato spazio per un singolo wchar_t, e punto a esso. Quindi si tenta di impostare il puntatore in modo che punti a una stringa (ricordare, solo al primo carattere), ma il tipo di stringa non è corretto.

Quello che hai è una stringa di char, "dovrebbe" essere L"Tony". Ma tutto quello che stai facendo qui sta perdendo la precedente allocazione di memoria perché il puntatore contiene un nuovo valore.

Piuttosto si desidera allocare spazio sufficiente per contenere l'intera stringa, quindi copiare la stringa nella memoria allocata. Questa è una pratica terribile, però; non fare mai nulla che ti renda necessario liberare esplicitamente memoria.

Basta usare std::wstring e andare avanti. std::wstring t = L"Tony";.Gestisce tutti i dettagli e non è necessario preoccuparsi di pulire nulla.

+2

IMO la risposta più corretta e, con l'uso di' std :: wstring', il miglior consiglio. – sbi

+0

@sbi: Perché grazie. :) – GManNickG

+1

Ottima risposta. –

5

Dato che sei uno sviluppatore C#, sottolineerò alcune cose che C++ fa diversamente.

Questo alloca un nuovo wchar_t e assegna a t

wchar_t* t = new wchar_t 

Questo è un array di costante char

"Tony" 

Per ottenere una costante prefisso matrice wchar_t con L

L"Tony" 

Questo è di puntare alla costante L "Tony" al posto del vecchio wchar_t e causa una perdita di memoria dal momento che il tuo wchar_t non verrà mai rilasciato.

t = L"Tony" 

Questo crea una stringa di caratteri di larghezza (wchar_t) per tenere una copia di L "Tony"

std::wstring t = L"Tony" 

Credo che l'ultima riga è ciò che si desidera. Se hai bisogno di accedere al puntatore wchar_t, usa t.c_str(). Si noti che le stringhe C++ sono modificabili e vengono copiate su ciascun compito.

Il c modo per farlo sarebbe

const wchar_t* t = L"Tony" 

Questo non crea una copia e assegna solo il puntatore per puntare alla matrice wchar const