2010-09-17 11 views
12

He estado programando mal por bastante tiempo y solo me acabo de dar cuenta. Anteriormente creé muchas funciones que devuelven cadenas de caracteres como matrices de caracteres (o al menos sugerencias para ellas).¿Cómo devolver una matriz de caracteres creados en la función?

El otro día alguien señaló que cuando mis funciones regresan, las matrices de caracteres señaladas por mis funciones han salido del ámbito y esencialmente ahora estoy apuntando a un poco de memoria aleatoria (un puntero colgante desagradable).

No me di cuenta de esto por un tiempo porque las matrices de caracteres cuando salían a la consola no parecían estar dañadas (probablemente porque no había tiempo para sobrescribir esos datos). Sin embargo, me di cuenta de esto cuando estaba devolviendo un búfer de cadena (matriz de caracteres) generado al leer el puerto serie que con frecuencia estaba dañado.

Entonces, ¿qué mejor debería hacerlo?

Mi mal código es el siguiente:

#include <cstdlib> 
#include <iostream> 

using namespace std; 

char* myBadFunction(){ 
    char charArray[] = "Some string\n"; 
    char* charPointer = charArray; 
    return charPointer; 
} 


int main(int argc, char** argv) { 

    cout << myBadFunction(); 

    return 0; 
} 

entiendo que tal vez debería asignar memoria en el programa antes de llamar a la función o crear una variable global para poner la cadena devuelta, pero si mi función llamada es utilizado por muchos programas diferentes, ¿cómo debería saber el tamaño del búfer que se está transfiriendo con anterioridad y cuándo debería eliminarse?

El siguiente código también no hace lo que yo quiero que correctamente:

#include <cstdlib> 
#include <iostream> 

using namespace std; 

void fillArray(char* charPointer){ 
    char charArray[] = "Some string\n"; // Create string 
    charPointer = charArray; // Not correct, want to fill predefined array with created string 
    return; 
} 


int main(int argc, char** argv) { 

    char predefinedArray[50] = {0}; 
    fillArray(predefinedArray); 
    cout << predefinedArray; 

    return 0; 
} 

Quiero llenar la matriz que analiza el puntero puntos a, pero ésto no' sucede en el código de seguridad.

Además, ¿cuándo debería usar el nuevo comando [] para crear mi matriz? es necesario? y cuando debería llamar delete [] en él.

Muchas gracias por esto, es obviamente muy fundamental, pero algo que he estado haciendo mal desde hace un tiempo.

+1

es mejor que agregue el tipo de código que escribe en las etiquetas. – Stefanvds

+0

En cuanto a la segunda parte de su pregunta, deberá usar el bucle manual y copiar cada carácter en la segunda matriz o usar 'memcpy' ... – st0le

Respuesta

10

La manera más simple sería devolver un std::string, y si necesitabas acceso a la matriz de caracteres interna usa std::string::c_str().

#include <iostream> 
#include <string> 

using namespace std; 

string myGoodFunction(){ 
    char charArray[] = "Some string\n"; 
    return string(charArray); 
} 


int main(int argc, char** argv) { 
    cout << myGoodFunction(); 
    return 0; 
} 

Si necesita devolver algo que no sea una matriz de caracteres, recuerde que los punteros se pueden utilizar como iteradores. Esto le permite encapsular una matriz en un vector o una estructura similar:

vector<int> returnInts() { 
    int someNums[] = { 1, 2, 3, 4 }; 
    return vector<int>(someNums, someNums + 4); 
} 
+6

No estoy de acuerdo. Si bien esto resuelve el problema actual, no explica los problemas del uso de matrices de otros tipos. No rechazaré, eso sería injusto, pero una mejor respuesta explicaría los problemas con su código inicial. –

+0

Yay for 'std :: string', las antiguas matrices C son * así que * no C++ ... – fredoverflow

+1

@Alexander: Buen punto. He actualizado mi respuesta para reflejar su comentario. – Paul

6

Usted tiene dos opciones para devolver una matriz en C++. Puede completar la memoria preasignada (buena), o asignar su propia dentro de la función y devolverla (mal). La razón por la que se prefiere la primera es porque refuerza la eliminación adecuada de la memoria asignada.

Un ejemplo básico sería el siguiente aspecto:

void fillArray(char* buffer, int sz) { 
    char text[] = "hello there!"; 
    if (sizeof(text)>sz) { 
    // overflow! Buffer is too small! 
    return; 
    } 
    for (int n=0;n<sizeof(text);n++) { 
    buffer[n] = text[n]; 
    } 
} 

int main() { 
    char* buffer = new char[30]; // allocates a buffer of 30 bytes. 
    fillArray(buffer,30); 
    cout << buffer; 
    delete [] buffer; 
} 

/* note that it would be easier to use static memory in this example */ 

No es difícil cuando se piensa en el problema.

+0

Esto resuelve el problema, excepto cuando llamo nuevo [] y cuando borro []? Y, además, ¿qué pasa si la cadena añadida es asignada dinámicamente por cin >> string? ¿a quién debería la función interna conocer el tamaño del búfer que se le pasa? – Zac

+0

Usted asigna la memoria en la función principal. La función no necesita conocer el tamaño del búfer a menos que exista la posibilidad de un desbordamiento. Actualizaré mi respuesta por ti. –

1

Declare la matriz como variable "estática" y devuelva con su dirección. Este código funciona, pero hace una advertencia:

#include <cstdlib> 
#include <iostream> 
using namespace std; 

char* myBadFunction(){ 
    static char charArray[] = "Some string\n"; // insert "static" 
    // char* charPointer = charArray; 
    return charArray;    // charArray is a pointer to the static array 
}         // after returning static varibles stay safe 
int main(int argc, char** argv) { 
    cout << myBadFunction(); 
    return 0; 
} 
+0

¿Cuándo se liberará la memoria utilizada por la matriz estática? ¿Tengo que hacer eso yo mismo? –

1

"Algunos cadena \ n" es una cadena literal y por lo tanto existirá durante toda la vida del programa, por lo que el siguiente sería válida:

#include <cstdlib> 
#include <iostream> 

using namespace std; 

char* myGoodFunction(){ 
    char* charPointer = "Some string\n"; 
    return charPointer; 
} 

int main(int argc, char** argv) { 
    cout << myGoodFunction(); 

    return 0; 
} 

Por supuesto, esto solo es útil si la función siempre devuelve la misma cadena. Si la cadena devuelta puede variar (generalmente el caso), entonces puede declarar la matriz de caracteres en su función como estática y devolver su dirección (como ya se ha sugerido).

Cuestiones relacionadas