elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Estamos en la red social de Mastodon


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  [SOLUCIONADO] C++ - Error con memoria dinámica: ¿Puntero por referencia?
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: [SOLUCIONADO] C++ - Error con memoria dinámica: ¿Puntero por referencia?  (Leído 6,059 veces)
xaps

Desconectado Desconectado

Mensajes: 157



Ver Perfil
[SOLUCIONADO] C++ - Error con memoria dinámica: ¿Puntero por referencia?
« en: 21 Noviembre 2013, 01:21 am »

Dadas dos funciones, necesito pasar un puntero por referencia de una función a la otra para obtener los datos de una lista de strings (las dos funciones están dentro de la misma clase).
El problema viene dado a que desde un objeto de esa clase, necesito acceder a datos privados de otro objeto del mismo tipo (una lista de strings). Entonces, la solución más eficiente que se me ha ocurrido es crear un puntero de tipo vector<string> vect, pasarlo por referencia a la otra función, y en esa hacer vect = new vector<string> (N), donde N es el tamaño de la lista de la que quiero obtener sus elementos, pero me da errores de compilación y no consigo resolverlos.

Os adjunto el código de las dos funciones implicadas y el error recibido al compilar (compilo en Linux con G++):

NOTA: La primera función empieza en la línea 33, y la segunda en la línea 71, por lo que los errores saltan en las líneas marcadas con el comentario ERROR EN ESTA LÍNEA.

Código
  1. #include <vector>
  2. #include <list>
  3.  
  4. list<string> lista; //Esto está declarado en la parte privada de la clase
  5.  
  6. void Objeto::fusion_objeto(const Objeto &rev)
  7. {
  8.  //Declaro puntero
  9.  vector<string> *s = NULL;
  10.  rev.func_aux(s);
  11.  int n = s->size();
  12.  for (int i = 0; i < n; ++i) lista.insert(lista.begin(), s[i]); //ERROR EN ESTA LÍNEA
  13.  delete s;
  14. }
  15.  
  16. void Objeto::func_aux(vector<string>* &s)
  17. {
  18.  int N = lista.size();
  19.  s = new vector<string> (N);
  20.  list<string>::iterator it = lista.begin();
  21.  for (int i = 0; i < N; ++i)
  22.  {
  23.    s[i] = *it; //ERROR EN ESTA LÍNEA
  24.    ++it;
  25.  }
  26. }
  27.  

Error de la primera función:
Código:
Objeto.cpp: In member function ‘void Objeto::fusion_objeto(const Objeto&)’:
Objeto.cpp:39:69: error: no matching function for call to ‘std::list<std::basic_string<char> >::insert(std::list<std::basic_string<char> >::iterator, std::vector<std::basic_string<char> >&)’
Objeto.cpp:39:69: note: candidates are:
In file included from /usr/include/c++/4.7/list:65:0,
                 from Objeto.hpp:8,
                 from Objeto.cpp:1:
/usr/include/c++/4.7/bits/list.tcc:99:5: note: std::list<_Tp, _Alloc>::iterator std::list<_Tp, _Alloc>::insert(std::list<_Tp, _Alloc>::iterator, const value_type&) [with _Tp = std::basic_string<char>; _Alloc = std::allocator<std::basic_string<char> >; std::list<_Tp, _Alloc>::iterator = std::_List_iterator<std::basic_string<char> >; std::list<_Tp, _Alloc>::value_type = std::basic_string<char>]
/usr/include/c++/4.7/bits/list.tcc:99:5: note:   no known conversion for argument 2 from ‘std::vector<std::basic_string<char> >’ to ‘const value_type& {aka const std::basic_string<char>&}’
In file included from /usr/include/c++/4.7/list:64:0,
                 from Objeto.hpp:8,
                 from Objeto.cpp:1:
/usr/include/c++/4.7/bits/stl_list.h:1104:7: note: void std::list<_Tp, _Alloc>::insert(std::list<_Tp, _Alloc>::iterator, std::list<_Tp, _Alloc>::size_type, const value_type&) [with _Tp = std::basic_string<char>; _Alloc = std::allocator<std::basic_string<char> >; std::list<_Tp, _Alloc>::iterator = std::_List_iterator<std::basic_string<char> >; std::list<_Tp, _Alloc>::size_type = long unsigned int; std::list<_Tp, _Alloc>::value_type = std::basic_string<char>]
/usr/include/c++/4.7/bits/stl_list.h:1104:7: note:   candidate expects 3 arguments, 2 provided
/usr/include/c++/4.7/bits/stl_list.h:1125:9: note: template<class _InputIterator> void std::list::insert(std::list<_Tp, _Alloc>::iterator, _InputIterator, _InputIterator) [with _InputIterator = _InputIterator; _Tp = std::basic_string<char>; _Alloc = std::allocator<std::basic_string<char> >]
/usr/include/c++/4.7/bits/stl_list.h:1125:9: note:   template argument deduction/substitution failed:
Objeto.cpp:39:69: note:   candidate expects 3 arguments, 2 provided


Error de la segunda función:
Código:
Objeto.cpp: In member function ‘void Objeto::func_aux(std::vector<std::basic_string<char> >*&)’:
Objeto.cpp:78:13: error: no match for ‘operator=’ in ‘*(s + ((sizetype)(((long unsigned int)i) * 24ul))) = it.std::_List_iterator<_Tp>::operator*<std::basic_string<char> >()’
Objeto.cpp:78:13: note: candidate is:
In file included from /usr/include/c++/4.7/vector:70:0,
                 from Objeto.hpp:9,
                 from Objeto.cpp:1:
/usr/include/c++/4.7/bits/vector.tcc:161:5: note: std::vector<_Tp, _Alloc>& std::vector<_Tp, _Alloc>::operator=(const std::vector<_Tp, _Alloc>&) [with _Tp = std::basic_string<char>; _Alloc = std::allocator<std::basic_string<char> >]
/usr/include/c++/4.7/bits/vector.tcc:161:5: note:   no known conversion for argument 1 from ‘std::basic_string<char>’ to ‘const std::vector<std::basic_string<char> >&’

Tiene pinta de que acceda mal a las posiciones del vector dinámico. He probado con lo siguiente, pero lógicamente no funciona.
Código:
*(s[i])

¿Alguna idea?

Saludos y gracias


« Última modificación: 22 Noviembre 2013, 02:32 am por xaps » En línea

"The programmers of tomorrow are the wizards of the future" - Gave Newel
amchacon


Desconectado Desconectado

Mensajes: 1.211



Ver Perfil
Re: C++ - Error con memoria dinámica: ¿Puntero por referencia?
« Respuesta #1 en: 21 Noviembre 2013, 12:15 pm »

Muy abstracto *_*

Citar
El problema viene dado a que desde un objeto de esa clase, necesito acceder a datos privados de otro objeto del mismo tipo (una lista de strings). Entonces, la solución más eficiente que se me ha ocurrido es crear un puntero de tipo vector<string> vect, pasarlo por referencia a la otra función
C++ te permite el uso de variables "referencia". Son más seguras y más naturales que los punteros:

Código
  1. int cosa = 0;
  2. int &objeto = cosa;
  3.  
  4. cout<<objeto<<endl;
  5.  
  6. cosa = 1;
  7.  
  8. cout<<objeto<<endl;

No entiendo bien tú código pero un vector se puede copiar con el constructor copia:

Código
  1. vector<string> tuVector(otroVector);

Si usas un puntero, tendrías que poner eso en el new. Pero repito que no necesitas punteros para nada.


Por otro lado si quieres insertar un elemento al principio, te vendría mejor push_front:
http://www.cplusplus.com/reference/list/list/push_front/




En línea

Por favor, no me manden MP con dudas. Usen el foro, gracias.

¡Visita mi programa estrella!

Rar File Missing: Esteganografía en un Rar
xaps

Desconectado Desconectado

Mensajes: 157



Ver Perfil
Re: C++ - Error con memoria dinámica: ¿Puntero por referencia?
« Respuesta #2 en: 21 Noviembre 2013, 13:47 pm »

Muy abstracto *_*
C++ te permite el uso de variables "referencia". Son más seguras y más naturales que los punteros:

Código
  1. int cosa = 0;
  2. int &objeto = cosa;
  3.  
  4. cout<<objeto<<endl;
  5.  
  6. cosa = 1;
  7.  
  8. cout<<objeto<<endl;

...

Por otro lado si quieres insertar un elemento al principio, te vendría mejor push_front:
http://www.cplusplus.com/reference/list/list/push_front/

Al ser parte de un trabajo de la universidad, tengo varias restricciones. Entre ellas, están no poder hacer funciones que retornen tipos complejos (como lo son vectores o listas), no poder usar ciertos métodos (push_front lo tenemos prohibido tanto en listas como vectores) y el uso de & lo tengo restringido para pasar parametros por referencia en las funciones. Los métodos no deberian cambiar por temas de restricciones como ya he dicho. Lo ideal sería encontrar el problema con el puntero sin cambiar la estructura de las funciones.

No entiendo bien tú código pero un vector se puede copiar con el constructor copia:

Código
  1. vector<string> tuVector(otroVector);

Si usas un puntero, tendrías que poner eso en el new. Pero repito que no necesitas punteros para nada.

Estoy intentando pasar el contenido de una lista a un vector, por lo que el uso del constructor-copia de <vector> no serviría para este caso.

Si hay algo que no entiendes de mi código coméntalo y intentaré explicártelo lo mejor que pueda. Lo mejor para estos temas es que todos los que nos involucremos aprendamos algo nuevo.

Saludos
« Última modificación: 21 Noviembre 2013, 13:53 pm por xaps » En línea

"The programmers of tomorrow are the wizards of the future" - Gave Newel
lapras

Desconectado Desconectado

Mensajes: 140



Ver Perfil WWW
Re: C++ - Error con memoria dinámica: ¿Puntero por referencia?
« Respuesta #3 en: 21 Noviembre 2013, 14:16 pm »

El segundo argumento de lista.insert() debería ser un número.
Además de eso, dado que s es un puntero debes acceder los elementos así:
Código
  1. (*s)[i]
en vez de así:
Código
  1. s[i]
Otra cosa es que no tiene sentido pasar un puntero por referencia:
Código
  1. vector<string>* &s
En línea

xaps

Desconectado Desconectado

Mensajes: 157



Ver Perfil
Re: C++ - Error con memoria dinámica: ¿Puntero por referencia?
« Respuesta #4 en: 21 Noviembre 2013, 15:19 pm »

El segundo argumento de lista.insert() debería ser un número.
Además de eso, dado que s es un puntero debes acceder los elementos así:
Código
  1. (*s)[i]
en vez de así:
Código
  1. s[i]
Otra cosa es que no tiene sentido pasar un puntero por referencia:
Código
  1. vector<string>* &s

El segundo parametro del insert no debería ser un número, ya que la lista se ha declarado como lista de string.

En cuanto a la solución dada, funciona, muchas gracias. No sé como no se me había pasado por la cabeza esto... Supongo que por la poca experiencia que tengo en memoria dinámica.

Una duda:
Código:
*s[i]
Esto no me funcionaba porque lo cogía todo como un puntero, ¿verdad? Es decir, como si fuera un vector de punteros.

Y la segunda parte en la que me dices que no tiene sentido pasar un puntero por referencia, supongo que es porque aunque se cree una copia del puntero, la posición de memoria a la que apunta será modificada igualmente, ¿cierto? Por lo que el puntero de la primera función ya apuntará al valor modificado.

Saludos
En línea

"The programmers of tomorrow are the wizards of the future" - Gave Newel
lapras

Desconectado Desconectado

Mensajes: 140



Ver Perfil WWW
Re: C++ - Error con memoria dinámica: ¿Puntero por referencia?
« Respuesta #5 en: 21 Noviembre 2013, 23:05 pm »

Tienes razón en lo del insert, fallo mío.

Lo del puntero es por el tema de las precedencias, el operador [] es el que tiene más precedencia junto con otros. Entonces esto *s es equivalente a esto *(s).
Como bien has dicho, lo que haces es coger un elemento e intentas usarlo como si fuese un puntero.

Lo de pasar un puntero por referencia lo digo porque los parametros que se pasan por refrencia suelen ser estructuras de tamaño considerable.  Eso es porque copiar dicha estructura sería muy costoso. En realidad pasar algo por referencia es como pasar un puntero a ese algo, sólo que dentro de la función no necesitas hacer tantos castings(queda feo tanto paréntesis), y además al llamar a la función pasas el parametro como si fuese por valor(te ahorras el &). Volviendo a lo de pasar un puntero por referencia, un puntero ocupa poco, no necesitas pasar una refencia a un puntero(es como si pasas un puntero a un puntero). No esta mal aunque si lo pasas por valor ahorras un acceso a memoria.
En línea

xaps

Desconectado Desconectado

Mensajes: 157



Ver Perfil
Re: C++ - Error con memoria dinámica: ¿Puntero por referencia?
« Respuesta #6 en: 22 Noviembre 2013, 02:32 am »

Tienes razón en lo del insert, fallo mío.

Lo del puntero es por el tema de las precedencias, el operador [] es el que tiene más precedencia junto con otros. Entonces esto *s es equivalente a esto *(s).
Como bien has dicho, lo que haces es coger un elemento e intentas usarlo como si fuese un puntero.

Lo de pasar un puntero por referencia lo digo porque los parametros que se pasan por refrencia suelen ser estructuras de tamaño considerable.  Eso es porque copiar dicha estructura sería muy costoso. En realidad pasar algo por referencia es como pasar un puntero a ese algo, sólo que dentro de la función no necesitas hacer tantos castings(queda feo tanto paréntesis), y además al llamar a la función pasas el parametro como si fuese por valor(te ahorras el &). Volviendo a lo de pasar un puntero por referencia, un puntero ocupa poco, no necesitas pasar una refencia a un puntero(es como si pasas un puntero a un puntero). No esta mal aunque si lo pasas por valor ahorras un acceso a memoria.

Muchas gracias por la explicación, me has resuelto la duda.

Saludos
En línea

"The programmers of tomorrow are the wizards of the future" - Gave Newel
lapras

Desconectado Desconectado

Mensajes: 140



Ver Perfil WWW
Re: C++ - Error con memoria dinámica: ¿Puntero por referencia?
« Respuesta #7 en: 22 Noviembre 2013, 17:16 pm »

Muchas gracias por la explicación, me has resuelto la duda.

Saludos

Me alegro  ;)
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Cuestión puntero y referencia
Programación C/C++
darkvidhack 4 3,254 Último mensaje 10 Mayo 2011, 16:31 pm
por satu
pasar por referencia un puntero
Programación C/C++
m@o_614 2 7,303 Último mensaje 18 Enero 2014, 18:13 pm
por rir3760
Problema leyendo cadenas con memoria dinamica [solucionado]
Programación C/C++
dato000 9 7,148 Último mensaje 24 Enero 2014, 18:37 pm
por dato000
Tengo un error con el paso de parámetros por referencia, en C (Solucionado)
Programación C/C++
DarkSorcerer 2 2,613 Último mensaje 24 Enero 2014, 00:22 am
por DarkSorcerer
Error con memoria dinámica en C++
Programación C/C++
Vivisnai 3 2,494 Último mensaje 1 Marzo 2016, 20:20 pm
por Vivisnai
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines