2010-09-30 14 views
5
struct run_male_walker_struct { 
     string male_user_name; 
     string show_name; 
}; 
typedef struct run_male_walker_struct run_male_walker_struct_t; 

en otra función:cadena de C++ en C struct, ¿es ilegal?

run_male_walker_struct_t *p = malloc(sizeof(struct run_male_walker_struct)); 

pregunta, ¿es ilegal? Como la cadena es una clase, su tamaño no puede determinarse por sizeof().

+6

Usted está equivocado. El tamaño de 'struct run_male_walker_struct' se puede determinar en tiempo de compilación por el operador' sizeof'. Sin embargo, al usar 'malloc()' no se construirán las instancias 'std :: string'. – wilx

+3

@wilx Estás en lo correcto, pero esto debería ser una respuesta, en lugar de un comentario :) – KSchmidt

+4

¿No es la frase "C struct" poco engañosa ...? Además, la consulta parece estar en "C++ struct" :) – Arun

Respuesta

5

Esto es ilegal, pero no por las razones que estás pensando.

La diferencia entre std::malloc()/std::free() y new/delete es que este último llame constructores/destructores, mientras que el primero no lo hará. La expresión

void* p = std::malloc(sizeof(run_male_walker_struct)) 

devolverá un blob de memoria no inicializada en la que no se llama a ningún constructor. No se debe tocar con un palo de diez pies - a excepción de la invocación de un constructor en él:

run_male_walker_struct* pw = new(p) run_male_walker_struct; 

Si lo hace, tendrá que hacer a la inversa, también:

pw->~run_male_walker_struct(); 

antes liberas la memoria:

std::free(p); 

Sin embargo, eso deja la pregunta de por qué quieres hacer eso.
La única razón para hacer esto debe ser cuando desee separar la asignación de memoria de la construcción (como, por ejemplo, en un asignador de grupo). Pero si lo necesita, lo mejor es esconderse detrás de alguna interfaz. Uno natural estaría sobrecargando new y deletepor clase. Además, std::vector hace esto internamente.

1

Usar malloc() funcionaría, pero usarlo solo creará suficiente espacio para su estructura. Esto significa que no podrá usar sus cadenas correctamente, ya que no se inicializaron con sus constructores.

Tenga en cuenta que las clases de cadena no tienen su contenido en la memoria de la pila, sino en la memoria dinámica, que no afecta el tamaño de la estructura. Todas las clases y estructuras tienen un tamaño estático, que se conoce en tiempo de compilación (si se definió la estructura/clase).

Sugiero usar nuevas. Usar malloc será rellenar las cadenas.

Esto plantea una pregunta mía, ¿cómo se llamó a los constructores a la creación de instancias asignadas dinámicamente en C (no existían cosas tales como constructores en C?). Si es así, otra razón más contra el uso puro de C.

+0

C no tiene constructores ni destructores. – KSchmidt

+0

No hay invocación de función implícita en C ... si desea inicializar un objeto al que llamó usted mismo el "constructor" (que puede o no haber incrustado la llamada malloc()). Por ejemplo, una API podría permitir 'p = new_string (" value inicial ");', con la implementación determinando si 'free (p)' o 'delete_string (p)' era necesaria en el otro extremo. O incluso peor ala 'p = (struct string *) malloc (bytes); string_init (p); ... string_done (p); free (p) ', o el enfoque común no encapsulado' p = ... malloc(). p-> tamaño = 0; ... '... –

1

Estoy bastante seguro de que esto es legal porque se conocerá el tamaño del objeto std :: string incluso si no se conocen las longitudes de las cadenas. Sin embargo, los resultados pueden no ser los esperados porque malloc no llamará a constructores.

Prueba esto:

std::string testString1("babab"); 
std::string testString2("12345678"); 
std::string testString3; 
std::cout <<" sizeof(testString1)" <<sizeof(testString1) << std::endl; 
std::cout <<" sizeof(testString2)" <<sizeof(testString2) << std::endl; 
std::cout <<" sizeof(testString3)" <<sizeof(testString3) << std::endl; 

En mi máquina me da el siguiente resultado:

sizeof(testString1)8 
sizeof(testString2)8 
sizeof(testString3)8 

También hay alguna razón usted no está utilizando:

run_male_walker_struct_t *p = new(struct run_male_walker_struct); 

Este es la forma correcta de hacerlo en C++, usar malloc es casi seguro un error.

EDIT: ver esta página para una explicación más detallada de la nueva vs malloc en C++: http://www.codeproject.com/KB/tips/newandmalloc.aspx

5

No es muy seguro de lo que estás pidiendo aquí ... Para ser claro, la palabra clave es una struct válida Designación de C++, que funciona de forma casi idéntica a class excepto por la privacidad predeterminada. Entonces, si está compilando con g ++ e incluyendo la biblioteca de cadenas, esta es una declaración válida.

Sin embargo, llamar con malloc() le dará la memoria, no realmente construirá los valores dentro de esa estructura. Podría crear una instancia más apropiada llamando a su constructor predeterminado.

3

La definición de estructura en sí es correcta. Resulta que es un agregado no POD. Pero debería preferir el uso de new y delete sobre malloc y free porque estos manejan la construcción y la destrucción correctamente.Si desea seguir usando malloc y libre usted tiene que utilizar la colocación de nuevo para construir adecuadamente el objeto e invocar el destructor manualmente para destruirlo antes de liberarlo:

#include <new> 
... 
run_male_walker_struct *p = (run_male_walker_struct*) 
    malloc(sizeof(run_male_walker_struct)); 
new(p) run_male_walker_struct; // <-- placement-new 
... 
p->~run_male_walker_struct(); // <-- pseudo destructor call 
free(p); 

O simplemente:

run_male_walker_struct *p = new run_male_walker_struct; 
... 
delete p; 

por cierto: el typedef no es necesario en C++

1

¿Qué tal

run_male_walker_struct_t * p = new run_male_walker_struct_t: 
2

Trate de no usar malloc, si está en C++. Usar NEW es una mejor alternativa, cuando navegas por el código NEW(), te darás cuenta de que llama malloc !!!

Las ventajas de utilizar NEW es que llamará al constructor de su clase instanciado.

Otro comentario de menor importancia, el código que ha proporcionado no debe ser compilables:

run_male_walker_struct_t *p = malloc(sizeof(struct run_male_walker_struct)); 

debería ser

run_male_walker_struct_t *p = (run_male_walker_struct_t*)malloc(sizeof(struct run_male_walker_struct)); 

esto se debe a malloc devolverá un void *.

1

La respuesta depende de lo que quiere decir con "C struct".

Si quiere decir "una estructura que es válida bajo el lenguaje C", entonces la respuesta es obviamente: contiene un tipo de datos que no es válido C, por lo que la estructura tampoco es válida.

Si se refiere a un tipo de C++ POD, la respuesta es no, no es ilegal, pero la estructura ya no es un tipo POD (porque para ser POD, todos sus miembros deben ser POD también, y std::string no)