Buen Estilo

9 views
Skip to first unread message

Hichokei

unread,
Nov 11, 2008, 6:20:18 AM11/11/08
to Grupo de usuarios de C++ de la UGR

Hola a todos.

Me enteré hace poco de que estaba este grupo de programadores de C++.
Y por empezar con algo, me gustaría saber que consideráis que debe ser
obligatorio cumplir para que se pueda decir que un programa escrito en
C++ tiene estilo.

Es decir, yo por ejemplo obligaría a que todas las llaves fueran
abajo, y nunca después, como:

if (a<b)
{
.....
}

O por ejemplo, hay convenciones BSD que dicen que cada variable tiene
que tener la primera letra indicando el tipo de variable que es:

int iValor;
string sCadena;

¿¿Qué creéis que denota que un programa esté bien escrito, y que
además permita ser legible más fácil mente?? ¿Conocéis algún documento
que hable sobre ello?

JJ Merelo

unread,
Nov 11, 2008, 6:26:48 AM11/11/08
to gucp...@googlegroups.com
Gracias por romper el hielo. Dejé de programar C++ hace cierto tiempo, pero en aquella época se consideraba importante que, cualquiera que fuera el estilo, debería ser consistente.

En Perl, por otro lado, se considera mala práctica usar CamelCaps (como aString) y aconseja usar la convención a_string. Creo que la razón es porque en caso de siglas no se sabe muy bien donde empieza una palabra y acaba otra; el subrayado es más legible y representa la misma cantidad de trabajo (aproximadamente).

En cuanto al resto, suelo usar las convenciones que me da el modo Emacs correspondiente, no le doy muchas vueltas.

Saludos
--
JJ

Mario

unread,
Nov 11, 2008, 6:26:57 AM11/11/08
to gucp...@googlegroups.com
Hola,

Pues yo diria que las llaves vayan después del if o debajo, pero siempre cerradas a la misma altura.

Luego hay gente que no soporta que se haga esto: for(int i = 0; ...) y quieren que sea for(int i=0;i<29;i++)

Es decir, que vayan espacios.

Para mi la única regla sagrada es que el * del puntero vaya pegado al tipo, como decía Stroustrup: int* a y no int *a. Aunque eso ya no se ve, cuando entré en la carrera era lo usual.

El resto depende de gustos y para eso están los programas que te pasan de un estilo al que te gusta a ti.

GNU y el kernel de linux tienen sus guías de estilo. Y cada compañía grande normalmente también. Claro que luego empezamos a mezclar la terminología de C# y Java con la de C++.

A mi más que como se escriba el código lo que me preocuparía es que fuese código C++ y no C con clases. Y luego que sea compatible.

Saludos.

Juan Pedro Bolívar Puente

unread,
Nov 11, 2008, 6:40:58 AM11/11/08
to gucp...@googlegroups.com
Personalmente que la unica característica del estilo es la
consistencia, es decir, que se apliquen las mismas reglas a todo el
programa al que afecte.

Después, pues para gustos los colores. Aquí debaten un poco sobre este
tipo de cosas.

http://en.wikipedia.org/wiki/Programming_style
http://en.wikipedia.org/wiki/Indent_style

En esos artículos podéis encontrar muchas guías de estilo de proyectos
importantes. Creo que yo tengo alguna más en los marcadores, cuando
tenga un rato las busco y os las envío.

Si hablais de preferencias personales:
Para C, GNU.
Para C++ y Java, K&R.

Y en cuanto a nomenclatura, es algo que en un principio me rayaba
bastante y cambiaba constantemente según evolucionaban arbitrariamente
mis gustos. Así que ahora lo que hago es usar la nomenclatura de la
biblioteca estándar de cada lenguaje. Esto es, en C y C++ todo en
minúsculas con _ salvo las macros (y los enum en C) que van en
mayúsculas.

Un saludo,
JP


2008/11/11 Hichokei <osca...@gmail.com>:

Victor Puertas

unread,
Nov 11, 2008, 6:51:04 AM11/11/08
to gucp...@googlegroups.com
El estilo debe ser el que haga el código más legible y procurando
emplear siempre las mismas reglas.
En micaso, con las variables suelo emplear notación CamelCase, es decir,
nombreDeVariable.
Para la definición de clases empleo upperCamelCase, es decir,
NombreDeLaClase.
Para la definición de métodos también suelo emplear CamelCase.

Las llaves me gusta ponerlas debajo y con la correspondiente tabulación:
if(...)
{
sentencia
}

Un saludo.

Hichokei escribió:

J. L. Pino

unread,
Nov 11, 2008, 7:56:14 AM11/11/08
to gucp...@googlegroups.com
A mí lo que más me desconcierta es la indentación con las estructuras switch-case, estoy acostumbrado a hacerlas así:
switch (foo)
{
case 1:
a += 2;
break;

default:
a += 2;
break;
}

¿Hay alguna forma más recomendable en las guías de estilo?

Pablo Reyes

unread,
Nov 11, 2008, 8:49:07 AM11/11/08
to Grupo de usuarios de C++ de la UGR
Había leído muchas veces el tema de poner las llaves una línea por
debajo del if/while/for/etc, pero realmente no se porqué. A mí me
parece más cómodo ponerla seguido:
if(a<b){
tralara
}

Supongo que tendré que acostumbrarme a usar esa "regla".

En cuanto al tema del for que se comentaba por ahí, yo lo hago con
espacios (pero nunca para las asignaciones), en plan:
for(int i=0; i<10; i++)

Otro tema es a la hora de declarar variables. He leído en algunos
sitios que es conveniente ( y la verdad que ayuda a leerlo bien) poner
los valores al mismo nivel cuando se declaran varias variables
seguidas, es decir:
string nombre= "manolito";
string apellido= "fernandez";
string direccion_ppal="blablaa";
int sueldo= 1200;

En general, pienso como la mayoría: lo importante es llevar un estilo
constante, aunque una serie de "normas de estilo" generales vienen
bien para que el código pueda pasar de manos de la forma más cómoda
posible.

Juan Pedro Bolívar Puente

unread,
Nov 11, 2008, 10:26:40 AM11/11/08
to gucp...@googlegroups.com
En GNU recomiendan abrazar con corchetes cada caso:

switch (var)
{
case 1:
{
printf ("Estoy en el caso 1.\n");
break;
}
default:
{
printf ("Estoy en el caso por defecto.\n");
break;
}
}

También recomiendan poner siempre el caso 'default', incluso aunque
estés cubriendo todos los valores posibles de un tipo o situación,
para evitar problemas con algunos compiladores antiguos.

Un saludo,
JP


2008/11/11 J. L. Pino <gala...@gmail.com>:

JJ Merelo

unread,
Nov 11, 2008, 11:11:30 AM11/11/08
to gucp...@googlegroups.com
En todo caso, un truco que suelo yo usar en Perl y que no recuerdo a quien le vi es cuando uno abre las llaves, escribir también la de cierre, sin soltar el pulgar del AtlGr. Así fijo que no se te olvida cerrarlas.
--
JJ

Miguel Sanchez

unread,
Nov 11, 2008, 12:07:07 PM11/11/08
to gucp...@googlegroups.com
A mí particularmente el rollo de dejar espacios en los fors, etc. me parece totalmente irrelevante.

Respecto a las llaves, yo soy partidario siempre de ponerlo en la linea de debajo del bucle o lo que sea, creo que a primera vista resulta mucho más clara la estructura, queda todo como más compacto.

De todas maneras en Unix existen varios programas de "autoindentado" para C (y supongo que C++), como indent mismamente, aunque a decir verdad jamás lo he llegado a usar y no sé si se limitará a sangrados o también colocará llaves y tal.

Respecto a la nomenclatura de las variables, clases, etc. cada vez tiendo más a ponerlo todo en minúsculas menos las constantes y las macros, como comentaban antes, aunque a lo largo de la carrera creo que a lo que más he tendido ha sido a formato "myGet()" para funciones y variables y "MyClase" para clases.

C++ Programming/Code/Style Conventions (incompleto) en wikibooks: http://en.wikibooks.org/wiki/C%2B%2B_Programming/Code_Style

Borja Molina Zea

unread,
Nov 11, 2008, 2:08:39 PM11/11/08
to gucp...@googlegroups.com
Lo que no soporto es que tanto en MP1 como en MP2 se utilice la siguiente nomenclatura para la designación de punteros: int *puntero , no sé a vosotros pero a mi me parece antinatural, lo veo mucho mas intuitivo de la manera int* puntero, el asterisco al lado del tipo de dato al q referencia y no alreves.

J. L. Pino

unread,
Nov 11, 2008, 4:46:24 PM11/11/08
to gucp...@googlegroups.com
Gracias por la aclaración Juan pedro, la verdad es que usar llaves en los case no me gustan nada, ¿no os da la sensación de que así no es necesario el break porque no va a continuar evaluando el siguiente caso?

J.J. lo de escribir siempre juntas las aperturas de corchetes o llaves yo siempre lo he hecho pero por vagueza xDD

NetBeans también da formato automático bastante bien excepto en algún caso concreto: en algún JSP creo recordar que se me volvía un poco loco y hoy con un código que nos han dado en prácticas de una asignatura y que ha hecho que me "regalase" unos cuantos Warnings también. Eran estructuras for terminadas con ; del estilo:
for(int i=0.........){

};

Oscar (Hichokei)

unread,
Nov 11, 2008, 5:36:49 PM11/11/08
to gucp...@googlegroups.com
Borja, Esto que dices del int* obligaría a declarar todas las variables en cada línea, impidiendo por ejemplo:

int* a, *c;

Gracias por todos los enlaces, he empezando a buscar he encontrado un montón de cosas.

He visto varios proyectiyos, como BCPP (Beautiful C++) http://invisible-island.net/bcpp/bcpp.html abandonado en el 95, uno más reciente, el GC GreatCode http://sourceforge.net/projects/gcgreatcode/ abandonado en 05, Artisic Style, cuya última revisión ha sido en Abril de 08 http://astyle.sourceforge.net/

Luego, un par de PDF que resumen un poco:
http://trevinca.ei.uvigo.es/~jgarcia/FP/manuales/guiaestilocmm.pdf
http://informatica.uv.es/iiguia/FP/Esticpp.pdf

He leído sobre el indent, pero parece que es solo para  C, no se que pasaría si se lo metemos a C++, pero en ningún lado habla de compatibilidad, más bien lo contrario.

Y un documento, cuan menos curioso. Los Diez mandamientos de C:

http://www.lysator.liu.se/c/ten-commandments.html



Sobre los corchetes en los Case. A mi me gustan personalmente mucho, no los he usado nunca, pero me parece muy buena idea. Y para recordar lo break los pondría después estilo do {} while:

switch()
{
   case 1:
   {
   ...
   } break;

   case 2:
   {
   ...
   } break;

   default:
   {
   } break;

}

Y, como se puede ver, yo Prohibiría poner las llaves en líneas diferentes, me pone de los nervios.

Y otra cosa que veo que ayuda es poner espacio entre los operadores de comparación:
if (a < b)

Además de una costumbre que tengo para los espacios, de ir poniendo diferentes niveles e espacios para ver más claro que es lo que e hay dentro de que:

if (  ! ( (funcion( a(), b, c) < 5) && seguir )  )

Es de forma que cada paréntesis más general, tiene  más espacios.

Víctor, yo también prefiero CamelCase para las variables, la barra baja me parece una pérdida de caracteres innecesaria, pues se lee igual o mejor con las mayúsculas.

Alfonso E. Romero

unread,
Nov 11, 2008, 6:05:55 PM11/11/08
to gucp...@googlegroups.com
Lo del int* tiene su lógica porque el tipo de "int* a" es "puntero a int", esto es, la estrella forma parte del tipo. De igual modo debiera actuarse con las referencias (tipo int&). Si mal no recuerdo, esto lo han recomendado varios autores, entre otros Brian Kernighan y Rob Pike en el "The practice of Programming" (un librito muy majo y fácil de leer que recomiendo, a pesar de ser C, no C++).
--
---
Alfonso E. Romero
Web: http://decsai.ugr.es/~aeromero
Blog: http://misvaguedades.blogspot.com
alfonso...@gmail.com

Juan Pedro Bolívar Puente

unread,
Nov 12, 2008, 2:13:04 AM11/12/08
to gucp...@googlegroups.com
Stroustoup me consta que también lo recomienda y es prácticamente una
obligación para todos los estilista de C++. Sin embargo, por ejemplo,
en la guía de estilo de Apache sí recomiendan decir "int *a".

Esto es por lo que ha comentado Oscar, que viene de los primeros
tiempos de C en los que el concepto de tipo no estaba definido como lo
está ahora en C. Digamos que en aquellos tiempos imperaba la filosofía
de que existen por un lado variables y por otro lado punteros (y por
otro punteros a punteros, etc...) y por tanto el tipo de "int a" y el
de "int *a" sería el mismo, pero sería uno una variable y otro un
puntero.

En C realmente no tiene relevancia porque no existe una abstracción de
tipo elaborada en C++ así que las dos filosofías son válidas. En
cambio en C++ sí es importante (y por eso sus autores lo resaltan)
tomar conciencia del significado de tipo y de lo que representa en ese
sentido int o int* o cualquier otro tipo, en cuanto a cojunto de
operaciones que es capaz de manipular. El concepto de tipo aumenta la
ortogonalidad del lenguaje y el puntero como tipo nos permite usarlo
como un iterador por su semántica análoga como tipo y escribir cosas
como:

int* vector = new int [16];
for (vector, vector+16, functor);

Un saludo,
JP


2008/11/12 Alfonso E. Romero <alfonso...@gmail.com>:

Alfonso E. Romero

unread,
Nov 12, 2008, 8:22:31 AM11/12/08
to gucp...@googlegroups.com
De todas formas (y esto es una opinión muy muy personalísima, OJO),
presenté mi PFC hace 3 años ya (un sistema de indexación y recuperación
de información estructurada para colecciones documentales en XML) y
prácticamente no usé punteros. Tiré de referencias (que no es lo mismo
pero puede servir para cosas similares) y sobre todo de iteradores (a fin
de cuentas la abstracción del concepto de puntero), contenedores de la STL,
y algoritmos de la biblioteca estándar. De hecho, un colega mío siempre
usa el dicho "para qué usar punteros teniendo la STL?".

Yo antes era un enemigo acérrimo de la STL y demás, pero creo que si
uno conoce bien la biblioteca estándar de C++ (algorithm, vector, ...)
no necesita usar punteros si su proyecto no requiere cosas a muy bajo
nivel. Además, usar contenedores y algoritmos de la STL redunda en un
código más limpio, y más libre de errores (puesto que éstos están
verificados, y su código está aparte en una biblioteca). Para más inri,
lo peor es que muchas veces el código es más eficiente, porque el
código de la libstdc++ normalmente está muy bien escrito, y es muy
eficiente.

En definitiva, que yo entiendo, me gusta y manejo el concepto de puntero
perfectamente, pero prefiero usar otras herramientas. Siendo muy
estrictos, el puntero es una herencia de C que no tendría por qué existir
si C++ no hubiera tenido por qué tener retrocompatibilidad con C
(que alguien me corrija si me equivoco, pero creo que es posible vivir
sin punteros).

Por cierto, el proyecto tendría que liberarlo. A ver si hablo con el jefe :).

Saludos,
Alf.

Oscar (Hichokei)

unread,
Nov 12, 2008, 9:45:08 AM11/12/08
to gucp...@googlegroups.com

Alfonso, comentarte que leí en el libro de Stroustrup que los punteros se pueden usar para indicar los valores pasados por referencia a funciones, vamos, lo que ahora se pone mucho en C# de ref y out. Ejemplo:

void intercambiar(int *a, int *b)
{
   int aux = (*a);
   (*a) = (*b);
   (*b) = aux;
}

int main()
{
   int var = 4;
   int tam = 10;
   int* vec = new int[15];

   intercambiar (&var, &tam);
}

Yo desde que lo vi, me gustó, y no me parece tanta complicación. Y a mi me deja muy claro que variables de las que paso son las que voy a modificar, y no me cuesta nada poner (*a) en vez de a.

Y aquí no se si quedaría más claro usar int* a, o int *a. Puesto que más que usar una variable vector de int, estamos desreferenciando a la variable. ¿Se podría distinguir? ¿O caeríamos en que el código tuviera menos estilo por usar esto de dos maneras?

Alfonso E. Romero

unread,
Nov 12, 2008, 11:06:32 AM11/12/08
to gucp...@googlegroups.com
Sobre C# no puedo opinar porque no tengo NPI (pero ninguna, ojo). Y a día de hoy no pienso tenerla, por mucho que Icaza esté dando por saquillo con Mono y demás ;).

El ejemplo que pones es un poco "rarillo"... En C++ podría hacerse fácilmente con referencias, dando menos lugar a error:
  void intercambiar (int &a, int& b)
  {
    int temp = a;
    a = b;
    b = temp;
  }

La llamada es más clara, en mi opinión: intercambiar(var, tam). De todas formas, yo prefiero usar std::swap(a,b) para intercambiar los valores de "a" y de "b", sean quienes sean "a" y "b" (suponiendo que son del mismo tipo y tal). En ese caso te ahorrarías programar la función "intercambia".

"Jodiendo un poco más la marrana", este código con referencias es tan o más eficiente que el código con punteros, puesto que una referencia es un "alias" en la tabla de símbolos, con lo cuál accederías directamente a las variables cuyo valor vas a intercambiar, y con los punteros, además de necesitar espacio para dos variables extra en la tabla de símbolos, y en la memoria (su contenido es la dirección de memoria de las dos variables cuyo contenido intercambias), necesitas dos accesos a memoria para acceder al contenido. Eso es matizable, porque supongo que estos casos tan fáciles pueden ser optimizados por el compilador, pero eso queda ya un poco lejos de mi conocimiento (quizás alguien que conozca más sobre optimización en compiladores podría confirmártelo); lo que sí es seguro es que en el mejorcísimo de los casos (un compilador que te optimice eso), el gasto en memoria y ciclos de reloj en la versión de punteros sería igual que en la versión con referencias, y en el caso peor, sería peor. Alguien hace un g++ -c -s -O3 de las dos versiones? (Yo es que estoy aquí de sobremesa medio aletargado y me cuesta cambiar de ventana xD...).

Lo dicho, con referencias usas código más limpio y seguramente más rápido (y si usas std::swap, menos código). Soy partidario de no usar punteros en C++.

Saludos,
Alfonso.

Juan Pedro Bolívar Puente

unread,
Nov 12, 2008, 11:11:42 AM11/12/08
to gucp...@googlegroups.com
2008/11/12 Alfonso E. Romero <alfonso...@gmail.com>:
> De todas formas (y esto es una opinión muy muy personalísima, OJO),
> presenté mi PFC hace 3 años ya (un sistema de indexación y recuperación
> de información estructurada para colecciones documentales en XML) y
> prácticamente no usé punteros. Tiré de referencias (que no es lo mismo
> pero puede servir para cosas similares) y sobre todo de iteradores (a fin
> de cuentas la abstracción del concepto de puntero), contenedores de la STL,
> y algoritmos de la biblioteca estándar. De hecho, un colega mío siempre
> usa el dicho "para qué usar punteros teniendo la STL?".
>
> Yo antes era un enemigo acérrimo de la STL y demás, pero creo que si
> uno conoce bien la biblioteca estándar de C++ (algorithm, vector, ...)
> no necesita usar punteros si su proyecto no requiere cosas a muy bajo
> nivel. Además, usar contenedores y algoritmos de la STL redunda en un
> código más limpio, y más libre de errores (puesto que éstos están
> verificados, y su código está aparte en una biblioteca). Para más inri,
> lo peor es que muchas veces el código es más eficiente, porque el
> código de la libstdc++ normalmente está muy bien escrito, y es muy
> eficiente.
>

En general estoy de acuerdo. Aún así, hay situaciones en las que la
STL no proporciona la eficiencia suficiente, o no es apropiada. Por
ejemplo la STL genera, por su uso intensivo de plantillas, ejecutables
demasiado grandes para sistemas embebidos. También existen muchos
casos dónde es necesario un control mas directo sobre la disposición
en memoria de los elementos, o minimizar las llamadas a malloc y free.

Al respecto hay un interesantísimo artículo de la EA STL, una
modificación de la STL que usan en Electronic Arts dónde se demuestra
que el ingenio es capaz de unir elegancia y eficiencia:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2271.html

> En definitiva, que yo entiendo, me gusta y manejo el concepto de puntero
> perfectamente, pero prefiero usar otras herramientas. Siendo muy
> estrictos, el puntero es una herencia de C que no tendría por qué existir
> si C++ no hubiera tenido por qué tener retrocompatibilidad con C
> (que alguien me corrija si me equivoco, pero creo que es posible vivir
> sin punteros).
>

Sí, te equivocas :p. Básicamente porque las referencias de C++ son
estáticas, es decir, sólo se les puede asignar un valor en su
declaración. Además es imposible que una referencia apunte a "null",
porque una referencia supuestamente contiene es inmediatamente
"dereferencia" del objeto al que apunta, y uno no puede dereferenciar
null.

Aun así, cuando salga el C++0x con su unique_ptr, shared_ptr, weak_ptr
y las move-semantics para el auto_ptr, será posible vivir sin punteros
(aunque no siempre deseable).

Aún así, estoy de acuerdo en que en C++ se debe, y es posible,
minimizar el uso de punteros. De todas formas el RAII y los
destructores proporcionan una herramienta excelente para hacer un uso
sensato de los punteros, y también de otros recursos.

> Por cierto, el proyecto tendría que liberarlo. A ver si hablo con el jefe
> :).
>

Ánimo.

Un saludo,
JP

Juan Pedro Bolívar Puente

unread,
Nov 12, 2008, 11:28:18 AM11/12/08
to gucp...@googlegroups.com
2008/11/12 Alfonso E. Romero <alfonso...@gmail.com>:
> Sobre C# no puedo opinar porque no tengo NPI (pero ninguna, ojo). Y a día de
> hoy no pienso tenerla, por mucho que Icaza esté dando por saquillo con Mono
> y demás ;).
>
> El ejemplo que pones es un poco "rarillo"... En C++ podría hacerse
> fácilmente con referencias, dando menos lugar a error:
> void intercambiar (int &a, int& b)
> {
> int temp = a;
> a = b;
> b = temp;
> }
>

A lo que se refiere, es que de esa forma haces explícito el hecho de
que la variable puede ser referencia **en el momento de llamar a la
funcion**, gracias al & que le tienes que poner al argumento. Es una
cuestión de gustos, aunque lo normal y más comodo es usar referencias
en lugar de punteros para esas cosas.

> "Jodiendo un poco más la marrana", este código con referencias es tan o más
> eficiente que el código con punteros, puesto que una referencia es un
> "alias" en la tabla de símbolos, con lo cuál accederías directamente a las
> variables cuyo valor vas a intercambiar, y con los punteros, además de
> necesitar espacio para dos variables extra en la tabla de símbolos, y en la
> memoria (su contenido es la dirección de memoria de las dos variables cuyo
> contenido intercambias), necesitas dos accesos a memoria para acceder al
> contenido. Eso es matizable, porque supongo que estos casos tan fáciles
> pueden ser optimizados por el compilador, pero eso queda ya un poco lejos de
> mi conocimiento (quizás alguien que conozca más sobre optimización en
> compiladores podría confirmártelo); lo que sí es seguro es que en el
> mejorcísimo de los casos (un compilador que te optimice eso), el gasto en
> memoria y ciclos de reloj en la versión de punteros sería igual que en la
> versión con referencias, y en el caso peor, sería peor. Alguien hace un g++
> -c -s -O3 de las dos versiones? (Yo es que estoy aquí de sobremesa medio
> aletargado y me cuesta cambiar de ventana xD...).
>
> Lo dicho, con referencias usas código más limpio y seguramente más rápido (y
> si usas std::swap, menos código). Soy partidario de no usar punteros en C++.
>

Te has columpiao :p Una referencia y un puntero son idénticos a nivel
de implementación. Piensa que de otro modo no habría ningun
impedimento para usar esa supuesta tabla de símbolos, que no se a que
demonios te refieres (los símbolos son sólo para las variables
globales). Me he tomado la molestia de hacer el g++ -S para
demostrarlo. Sólo declaro swap() para que el -O3 no me haga un inline
(seguro que sin el -O3 no te fias):

void swap (int& a, int& b);

int main ()
{
int a, b;
swap (a, b);
return 0;
}

De la salida del .s me quedo con esto (la completa en el adjunto):

leal -12(%ebp), %eax
movl %eax, 4(%esp)
leal -8(%ebp), %eax
movl %eax, (%esp)
call _Z4swapRiS_

leal es la versión en ensamblador de &, es decir, te devuelve el valor
real de una dirección de memoria. -12(%ebp) es la posición dónde está
'a' (%ebp es el puntero a marco de pila) que copia a la posición
adecuada de la pila 4(%esp) para la llamada a función. Lo mismo hace
con el otro parámetro. call _Z4swapRiS_ es la llamada swap(), los
caracteres raros es el "name mangling" (¿cual es la traducción para
esto?) para C++ (se meten simbolos especiales para la información
adicional necesaria para la orientación objeta, por eso es necesario
extern "C" {} cuando se quiere hacer la interfaz con C).

Tardaría un segundo más en compilar el mismo ejemplo con punteros para
hacer la requetedemostración, pero eso se lo dejo a los desconfiados.
La argumentación teórica ya está ahi :p

Un saludo,
JP
prueba.s

Alfonso E. Romero

unread,
Nov 12, 2008, 12:14:53 PM11/12/08
to gucp...@googlegroups.com
Bueno, como dice el dicho "no te acostarás sin saber una cosa más". La verdad es que yo soy de la "vieja escuela" (sólo di C en la carrera) y digamos que mi conocimiento de C++ es relativamente bueno a nivel externo, pero por lo que acabo de ver no lo es tanto a nivel interno :D. Para confirmar tu versión (no es que sea desconfiado ;)), diré que he compilado la versión con punteros y usando todas las optimizaciones (sin optimizar, o1, O2 y O3) dan los mismos resultados de programa (los diff salen mínimos, apareciendo sólo cambios en las cadenas como el nombre del programa y la llamada a la función).

Suponía yo que con el tema de que una referencia es estática (en eso el puntero es claramente más versátil) se podía hacer una cosa más sofisticada a nivel de compilador. Por otra parte, es cierto que el parámetro hay que pasarlo a la función, y lo lógico y normal "apilar" la dirección de memoria de la variable que vas a referenciar en la función (puesto que no vas a copiar el valor primero para re-copiarlo después, cosa que además no cuadra con la semántica de paso de parámetros de c++). En definitiva, que por mucho que me pongo no hay más c*****s de implementar las referencias de otra forma.

Pregunto ahora yo, ¿no hay ninguna ventaja (internamente) de las referencias sobre los punteros, aparte de la limpieza de código, y de la posibilidad de declarar referencias constantes (lo cuál evita algunos bugs)?

Alfonso E. Romero

unread,
Nov 12, 2008, 12:29:33 PM11/12/08
to gucp...@googlegroups.com
Sobre el tema que comentas de la STL, yo entiendo que "no es la panacea" para tareas de eficiencia crítica, pero teniendo un cierto cuidado se pueden hacer las cosas razonablemente bien. Igualmente recomiendo el "Effective STL" de Scott Meyers para el que quiera leer del tema. Lo único malo es que uno al final acaba "STLizando" todo (si es que existe este término) y acaba haciendo programas-orientados-a-STL (por ejemplo, elige el algoritmo de la librería estándar más apropiado para una tarea antes de pensar en el algoritmo en general).

Pero vamos, que si todo fuera la eficiencia, no usaríamos lenguajes de script ;).

JJ Merelo

unread,
Nov 12, 2008, 12:33:35 PM11/12/08
to gucp...@googlegroups.com
Hola,


Pero vamos, que si todo fuera la eficiencia, no usaríamos lenguajes de script ;).

A ver, me habéis tocado la fibra sensible
1. Tengo un benchmark que, en algoritmos genéticos, Perl puede ser igual de rápido que Java
2. En ciencia, casi más importante que la eficiencia en tiempo de ejecución es la eficiencia en tiempo de creación, y en tiempo de revisión. Y no os metáis con el Perl, que si lo conoces, es tan legible como el C. De hecho, a mi me parece el C menos legible.
3. Cualquiera es capaz a base de profiling y de conocimiento de las estructuras más eficientes hacer en el lenguaje que conoce un programa que parta la pana. Si te vas a C++ porque es más eficiente, pero no tienes NPI de C++, seguro que lo harás más lento que en Ruby, que ya es decir lento.


--
JJ

J. L. Pino

unread,
Nov 12, 2008, 12:41:17 PM11/12/08
to gucp...@googlegroups.com
Es la una discusión de la lista pero va tomando vida propia xD

Sobre STL en estructuras de datos (gestión) aprendimos un poco, aunque un malvadísimo profesor me puso bastante mala cara cuando vio que usaba una cola con prioridad en una práctica (aunque es un profesor para echarle de comer aparte). He buscado en la web de la biblioteca y solo se ven libros en inglés sobre la STL. ¿Conoces alguno interesante en español Alfonso?

JJ Merelo

unread,
Nov 12, 2008, 12:50:10 PM11/12/08
to gucp...@googlegroups.com
Hay un tutorial escrito por una persona de mi departamento, pero posiblemente esté obsoleto, es de cuando el estándar estaba recién estrenado.

--
JJ

Alfonso E. Romero

unread,
Nov 12, 2008, 1:22:54 PM11/12/08
to gucp...@googlegroups.com
Hola a todos,

Jejejeje, JJ, he conseguido picarte :). Minipunto para mí :P. Sabes que yo también uso Perl para muchas tareas (que requieren eficiencia o no), y la verdad, estoy encantado (algún día escribiré un post tipo "por qué Perl salvó mi tesis", cuando corresponda). Pero si nos ceñimos a la eficiencia (en tiempo y en espacio), para algunas cosas estos lenguajes no son usables (por ejemplo, para trabajar en recuperación de información XML conozco gente de la UJI que han intentado hacer un SRI XML en Python y han desistido, porque literalmente "no les cabe en memoria").

Respecto a la STL, para "conocer" lo que hay, recomiendo el libro de Stroustrup (un tipo cuyo nombre nunca aprenderé a escribir). Ojo, una observación sobre el libro. La edición en español que yo compré (una con tapas negras que no puedo decirte de qué editorial era porque estoy muy lejos de mi casa), allá por 2002, era ho-rri-ble (la única edición que conozco de un libro de programación donde el códido de los programas estaba en un tipo de letra "times" y no "courier" o cualquiera de tipo "monospace"). Si hay varias ediciones, busca una que no tenga esto (seguramente una edición en inglés sea mejor). Eso sí, el libro es mucho más duro que los Deitel y compañía. Yo empecé a leerlo en segundo de carrera (aprendiendo C++ y OO por mi cuenta) y me costaba horrores (porque no es un libro típico de "aprenda a programar"). Si estás en cuarto o quinto, o si controlas C++ y la orientación a objetos (no sé cómo estarán ahora las Mp1 y 2) probablemente este comentario sobre. Si no, ahí queda. Pero para mí es una de las mejores inversiones que he hecho.

También, muchas veces, para tener una referencia rápida, yo me pasaba por la página de la stl => http://www.sgi.com/tech/stl/. No sería la primera vez que no te acuerdas si la cola tenía un método push_back o un add, o que no sabes qué diferencia hay entre pop y front. Esta página es una "referencia", y creo que puede estar algo anticuada, pero lo bueno es que siempre contiene algún código de ejemplo.

Por último, siempre nos quedará la famosa http://cppreference.com (aunque entrando ahora en ella veo que está de reformas y falta mucha de la información que había antes).

El libro de Scott Meyers "Effective STL" está muy bien, y lo puedes "encontrar por ahí" (no tengo que decir dónde, obviamente), pero no es para aprender a usar la STL. Más bien es para alguien que, conociendo esta biblioteca, quiere sacarle el máximo partido, y estudiar los "puntos oscuros" de la misma :).

PD.: a todo esto, llevo 3 años sin tocar casi C++. Soy un Java/Perl-guy, lo siento por las obsolescencias, chicos :D.

J. L. Pino

unread,
Nov 12, 2008, 1:48:26 PM11/12/08
to gucp...@googlegroups.com
Supongo que te referirás a esta:
Stroustrup, Bjarne
El lenguaje de programación C++ : edición especial / Bjarne Stroustrup
Madrid : Addison Wesley, 2002
XVI, 1050 p. : il. ; 25 cm.

Le echaré un ojo en la biblioteca para ver que tal está porque me puede venir bastante bien para unas prácticas que estoy haciendo ahora xD

Alfonso E. Romero

unread,
Nov 12, 2008, 2:02:52 PM11/12/08
to gucp...@googlegroups.com
El mismo. Que no tenga tapas negras, ojo ;).

J. L. Pino

unread,
Nov 12, 2008, 2:43:17 PM11/12/08
to gucp...@googlegroups.com
Había bastantes ejemplares cuyas tapas son rojas y había otro de tapas negras (duras) con pinta de ser bastante anterior que imagino será el tuyo.
Por desgracia se me ha olvidado la cartera en casa con el carnet universitario así que ya lo sacaré cuando me sea necesario xD

"Óscar (Hichokei)"

unread,
Nov 12, 2008, 3:11:14 PM11/12/08
to gucp...@googlegroups.com
Este libro me lo compré hace poco, con la idea de que iba a ser básico, pero que me ayudaría a conocer los detalles de C++.

Y nada más leer el prólogo, te dice que este libro no es para aprender, que si no sabes cojas otro. jajaja. Y esta muy bien, es de donde saqué lo de poner punteros en las funciones, y la dición de Addison Weskey (Tapas rojas blandas) tiene el código en Courrier New.

Muy ameno, aunque largo de cojones. Además viendo el final te describe el lenguaje de forma declarativa. Y tienes unas cuantas de páginas describiendo primero sintaxis, luego lexico y todo eso te acaba volviendo un poco loco. Con esto quiero decir que lo tiene todo.

Carlos Ureña

unread,
Nov 13, 2008, 6:10:10 AM11/13/08
to Grupo de usuarios de C++ de la UGR


On 12 nov, 18:14, "Alfonso E. Romero" <alfonsoerom...@gmail.com>
wrote:
> [....]
>
> Suponía yo que con el tema de que una referencia es estática (en eso el
> puntero es claramente más versátil) se podía hacer una cosa más sofisticada
> a nivel de compilador. Por otra parte, es cierto que el parámetro hay que
> pasarlo a la función, y lo lógico y normal "apilar" la dirección de memoria
> de la variable que vas a referenciar en la función (puesto que no vas a
> copiar el valor primero para re-copiarlo después, cosa que además no cuadra
> con la semántica de paso de parámetros de c++). En definitiva, que por mucho
> que me pongo no hay más c*****s de implementar las referencias de otra
> forma.
>
> Pregunto ahora yo, ¿no hay ninguna ventaja (internamente) de las referencias
> sobre los punteros, aparte de la limpieza de código, y de la posibilidad de
> declarar referencias constantes (lo cuál evita algunos bugs)?

Los punteros y las referencias pueden declararse a objetos no
modificables (const), así que eso no supone una diferencia. Las
referencias son inmutables por definición (una vez creada siempre
apunta al mismo sitio) , pero los punteros tambien pueden declararse
como inmutables (con int * const p). Las referencias pueden resolverse
(evitando direccionamiento indirecto en el codigo generado) en tiempo
de compilación a veces y a veces no, al igual que los punteros, eso
depende del compilador o el nivel de optimización, tampoco supone una
diferencia.

Por lo que recuerdo, el proposito de Stroustrup al introducir las
referencias es introducir un mecanismo en el lenguaje C++ que evita
dos problemas derivados del uso de punteros en C: el relacionado con
el tipo del dato apuntado, y el relacionado con la posibilidad de
intentar dereferenciar un puntero nulo o que apunta a una zona
equivocada. El primer problema ya no lo es tanto con las revisiones de
C a partir de primeros de los 90 (inicialmente los punteros a 'void'
eran un problema). El segundo sí que es un problema, y constituye la
mayor diferencia entre ambos mecanismos, es decir: por el diseño del
mecanismo, si usamos referencias exclusivamente (no hay punteros
involucrados) entonces una referencia, una vez que se ha declarado,
siempre apunta a una zona de memoria de nuestro proceso donde hay una
variable del tipo esperado, que estará ahí al menos mientras dure el
tiempo de vida de la referencia, con seguridad. La regla, por tanto,
es que podemos usar referencias en lugar de un puntero si alguna
precondicion o invariante nos permite saber que dicho puntero no puede
ser nulo nunca. En los casos en los que tengamos que hayamos previsto
que un puntero puede ser nulo, y que eso tenga algún significado
concreto en el programa, entonces no nos valen las referencias, hay
que usar punteros, y tener cuidado en no intentar nunca dereferenciar
un puntero nulo. Por supuesto, en lenguajes modernos, como Java y C#,
todo esto está resuelto mucho mejor.



Reply all
Reply to author
Forward
0 new messages