2010-06-24 30 views
8

¿Qué hay de malo en esto:wchar_t puntero

wchar_t * t = new wchar_t; 

t = "Tony"; 

pensé que podría utilizar un puntero wchar_t como una cadena ...

+0

posible duplicado de [Lo que está mal con este código ?] (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

Respuesta

25

el código tiene dos problemas.

Primero, "Tony" es un puntero a una cadena de char 's. L"Tony" es la cadena ancha adecuada.

En segundo lugar, asigna un único wchar_t a través de nuevo, y luego inmediatamente pierde la pista al reasignar el puntero a Tony. Esto da como resultado una pérdida de memoria.

+4

Para ampliar la explicación de Michael, la sintaxis correcta sería 'wchar_t * t = L" Tony ";'. Esto declararía un puntero e lo inicializaría para apuntar a la cuerda estática (ancha) "Tony". – bta

+3

La sintaxis debería ser 'wchar_t const * t = L" Tony ";'. Para ver por qué, considere la afirmación '* (t + 1) = L'i ';' – MSalters

-1

esto es totalmente erróneo. No hay necesidad de asignar dos bytes, haga t para apuntar a ellos, y luego sobrescriba el puntero t filtrando la memoria perdida para siempre.

Además, "Tony" tiene un tipo diferente. Uso:

wchar_t *t = L"Tony";

mi humilde opinión, mejor no utilizar en absoluto wchars - Ver https://stackoverflow.com/questions/1049947/should-utf-16-be-considered-harmful

+0

Probablemente un error tipográfico pero wchar_t t = ... debe ser wchar_t * t = ... –

+0

fixed, thx. a tpyo .. –

+4

También un wchar_t no es necesariamente dos bytes. En la versión de gcc, estoy usando un wchar_t de 4 bytes, y el estándar dice que es específico del compilador. Incluso puede ser un solo byte. –

5

Lo que esto hace es asignar primero un puntero a un recién asignado wchar_t en t, y luego intentar asignar una cadena no ancha en t.

¿Se puede usar std::wstring en su lugar? Eso manejará todas sus necesidades de administración de memoria para usted.

+0

wstring solo existe en MSVC. No es estándar. –

+6

@Pavel: Eso está muy mal. wstring es 'typedef''ed como' basic_string 'y existe en * cada * sistema/cadena de herramientas compatible con C++. – rubenvb

+6

@Pavel: §21.2/2: "El encabezado' 'también define dos clases de plantillas específicas' string' y 'wstring' y sus rasgos especiales." – GManNickG

0

puede, simplemente es que "Tony" es una cadena codificada, y son ANSI por defecto en la mayoría de los editores/compiladores. Si desea decirle al editor que está escribiendo una cadena Unicode, póngale un prefijo L, p. Ej. t = L"Tony".

Tiene otros problemas con su código, su asignación es asignar un único carácter Unicode (2 bytes), entonces está tratando de apuntar la variable original a la cadena constante, lo que filtra esos 2 bytes.

Si desea crear un buffer de datos y colocar los datos Unicode en él, que quiere hacer:

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

El tamaño de un wchar_t es específico del compilador y puede ser tan pequeño como 1 byte y tan grande como 4. –

11

Un puntero simplemente apunta a un solo valor. Esto es importante.

Todo lo que ha hecho tiene espacio asignado para un solo wchar_t, y apúntelo. Luego intenta configurar el puntero para apuntar a una cadena (recuerde, solo en el primer carácter), pero el tipo de cadena es incorrecto.

Lo que tiene es una cadena de char, "debería" ser L"Tony". Pero todo lo que hace aquí es filtrar su asignación de memoria anterior porque el puntero tiene un nuevo valor.

En lugar de asignar suficiente espacio para contener toda la cadena, copia la cadena en la memoria asignada. Esta es una práctica terrible, sin embargo; nunca haga nada que lo obligue a liberar memoria explícitamente.

Simplemente use std::wstring y continúe. std::wstring t = L"Tony";.Maneja todos los detalles, y no necesita preocuparse por limpiar nada.

+2

IMO la respuesta más correcta y, con el uso de' std :: wstring', el mejor consejo. – sbi

+0

@sbi: ¿Por qué, gracias? :) – GManNickG

+1

Excelente respuesta. –

5

Como usted es un desarrollador de C#, señalaré algunas cosas que C++ hace diferente.

Esto asigna un nuevo wchar_t y lo asigna a t

wchar_t* t = new wchar_t 

Esta es una matriz de char constante

"Tony" 

Para obtener una constante de matriz wchar_t prefijo con L

L"Tony" 

Esto se reasigna para apuntar a la constante L "Tony" en lugar de su viejo wchar_t y causa una pérdida de memoria ya que tu wchar_t nunca será lanzado.

t = L"Tony" 

Esto crea una cadena de caracteres de ancho (wchar_t) para mantener una copia de L "Tony"

std::wstring t = L"Tony" 

creo que la última línea es lo que quiere. Si necesita acceder al puntero wchar_t, use t.c_str(). Tenga en cuenta que las cadenas de C++ son mutables y se copian en cada asignación.

La forma c para hacer esto sería

const wchar_t* t = L"Tony" 

Esto no crea una copia y sólo asigna el puntero para señalar a la matriz wchar const