Pregunta

Al compilar el siguiente código:

void DoSomething(int Numbers[])
{
    int SomeArray[] = Numbers;
}

el compilador VS2005 se queja con el error C2440:'inicializando':no se puede convertir de 'int []' a 'int []'

Entiendo que en realidad está intentando lanzar un puntero a una matriz que no va a funcionar.Pero, ¿cómo se le explica el error a alguien que aprende C++?

¿Fue útil?

Solución

Hay tres cosas que hay que explicar a la persona que está tratando de ayudar a:

  1. Las matrices no se pueden pasar por el valor de una función en C ++. Para hacer lo que está tratando de hacer, tiene que pasar la dirección del inicio de la matriz a DoSomething() , así como el tamaño de la matriz en un int separada (bueno, size_t, pero yo no se molestan diciendo que) argumento. Puede obtener la dirección del inicio de alguna variedad myArray con el &(myArray[0]) expresión. Puesto que esto es una cosa tan común que quiere hacer, C ++ permite utilizar sólo el nombre de la matriz - por ejemplo, myArray - Para obtener la dirección de su primer elemento. (Que puede ser útil o confusa, dependiendo de la forma que se mire.) Para hacer las cosas aún más confuso, C ++ permite especificar un tipo de matriz (por ejemplo int Numbers[]) como un parámetro a una función, pero en secreto se trata de que el parámetro como si hubiera sido un declarado como un puntero (int *Numbers en este caso) - incluso se puede hacer dentro de Numbers += 5 DoSomething() a hacer que apunte a una matriz a partir de la sexta posición

  2. Cuando se declara una variable de matriz tales como SomeArray en C ++, debe proporcionar un tamaño explícito o una "lista de initialiser" , que es una lista separada por comas de valores entre los apoyos . No es posible que el compilador para inferir el tamaño de la matriz basada en otra matriz que se está tratando de inicializar con, porque ...

  3. No se puede copiar una matriz a otra, o inicializar una matriz de otro en C ++. Así que incluso si el Numbers parámetro era realmente una matriz (por ejemplo del tamaño de 1000) y no se un puntero, y se ha especificado el tamaño de SomeArray (de nuevo como decir 1000), la línea de int SomeArray[1000] = Numbers; sería ilegal.


Para hacer lo que quiere hacer en DoSomething(), primero preguntarse:

  1. ¿Es necesario cambiar cualquiera de los valores en Numbers?
  2. Si es así, es lo que quiero evitar que la persona que llama de ver esos cambios?

Si la respuesta a cualquiera de estas preguntas es "no", no, de hecho, es necesario hacer una copia de Numbers en el primer lugar -. Sólo tiene que utilizar como es, y olvidarse de hacer una matriz separada SomeArray

Si la respuesta a ambas preguntas es "Sí", tendrá que hacer una copia de Numbers en SomeArray y trabajar en ese lugar. En este caso, realmente debería hacer un SomeArray C ++ vector<int> en lugar de otra matriz, ya que esto realmente simplifica las cosas. (Explicar los beneficios de vectores sobre la asignación de memoria dinámica manual, incluyendo los hechos que puede inicializar de otras matrices o vectores, y van a llamar a los constructores de elementos cuando sea necesario, a diferencia de un memcpy() de estilo C).

Otros consejos

decir que hay tipos y tipos incompletas:

struct A;

Es un tipo incompleto de una estructura llamada A. Mientras

struct A { };

es un tipo completo de una estructura llamada A. El tamaño de la primera no se conoce todavía, mientras que el tamaño de la segunda se conoce.

Hay tipos de clases incompletas como la estructura anteriormente. Pero también hay tipos de matrices incompletas:

typedef int A[];

Esto es un tipo de matriz incompleta llamado A. Su tamaño no se conoce todavía. No se puede crear una matriz fuera de él, porque el compilador no sabe qué tan grande es la matriz. Pero se puede utilizar para crear una matriz, solamente Si inicializa enseguida:

A SomeArray = { 1, 2, 3 };

Ahora, el compilador sabe la matriz es una matriz int con 3 elementos. Si intenta inicializar la matriz con un puntero, el compilador no será más inteligente que antes, y se niegan, debido a que no se dará el tamaño de la matriz que se creará.

Al tratar de hacer que el mensaje de error más útil, el compilador es en realidad cosas confusas. A pesar de que el parámetro Numbers se declara como una matriz, C / C ++ no (no) en realidad pasar una matriz -. Numbers el parámetro es en realidad un puntero

Así que el error realmente debería decir "cannot convert from 'int *' to 'int []'"

Pero entonces no habría confusión - "Hey, no hay int* implicada en la expresión", alguien podría decir

.

Por esta razón, lo que realmente es mejor evitar parámetros de matriz - declararlos como punteros, ya que eso es lo que realmente está obteniendo de todos modos. Y la explicación a alguien que está aprendiendo C / C ++ debe educarlos en el hecho de que los parámetros de matriz no son una ficción -. Son realmente punteros

Cuando estoy tratando de explicar algo, yo siempre trato de bajar al nivel más bajo, y construir desde allí. Eso es que a mí me gusta aprender cosas, y me parece que las personas se sienten más cómodos si se inicia con los fundamentos que se conocen, y construir a partir de ahí.

En este caso, probablemente a empezar con algo como:

  

El compilador está tratando de hacer la   asignación, debido a que escribió una   operación de asignación. En C ++,   No se puede asignar directamente a una matriz,   porque no tiene una función de asignación   operador (de cualquier tipo, sólo se   inicializador y la indexación se apoya   para matrices). Debido a que los soportes C ++   operadores sobrecargados para los tipos, las   compilador busca entonces una sobrecarga   operador de asignación para la   "Asignado a" tipo que toma la   "Asignado a" tipo como argumento.   Dado que tampoco hay sobrecargado   operador para int [] que toma int []   como argumento, los errores de compilación en   la línea, y los errores que está diciendo   por qué el compilador no puede procesar la línea.

Sí, es algo excesivo vs acaba de decir algo sobre el conocimiento de su tamaño, tipos incompletas, etc. Me di cuenta que tampoco es completa (por ejemplo: no hay discusión de la asignación inicializador vs asignación normal, etc.). Sin embargo, mi objetivo es por lo general para hacer que la gente donde pueden averiguar la siguiente respuesta a sí mismos, y por eso normalmente se quiere diseñar el proceso de pensamiento para llegar a la respuesta.

Tal vez su respuesta podría ser: "Debido a que el compilador no sabe qué tan grande es la matriz."

Su ejemplo podría funcionar si hubo tamaños de matriz explícitos (quizá con un typedef para mayor claridad), y luego se puede explicar punteros mientras que la introducción asignaciones de tamaño variable.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top