2012-07-02 28 views
7

Esto puede ser una pregunta estúpida, pero tengo un código con la siguiente línea:¿Sintaxis extraña de C++?

Solver *S, *STP = S = 
UseDummySolver ? createDummySolver() : new STPSolver(true); 

Sé que el operador ternario pero es la signos igual que me confunden un poco. ¿Alguien puede darme alguna explicación? Gracias.

+18

Es un medio * muy feo * de asignar dos variables a la vez. * (quemar código [rs] como este con fuego) * – user7116

+3

Hay muchas razones por las cuales este código simplemente apesta. La parte de doble asignación es solo una de ellas. No usar RAII es otro. –

+0

Sí ... Ni siquiera me di cuenta de que es legal, ¡y nunca antes había visto eso! – steveha

Respuesta

16

en escrito, es

Solver *S; 
Solver *STP; 
S = UseDummySolver ? createDummySolver() : new STPSolver(true); 
STP = S; 

Es muy feo, sin embargo, yo no recomendaría hacerlo en el código.

La forma recomendada sería escribir como sigue (uso de inicialización, en lugar de asignación):

Solver *S = UseDummySolver ? createDummySolver() : new STPSolver(true); 
Solver *STP = S; 
+1

+1 Just beat me :) – NominSim

+2

¿Por qué no utilizar la inicialización, en lugar de la asignación? – Nawaz

+0

@Nawaz Él solo está explicando al OP lo que el código realmente _hace_. – NominSim

2

El operador ternario devuelve un valor; basado en el valor booleano UseDummySolver, devuelve un solucionador ficticio o devuelve una nueva instancia de STPSolver(). Este valor devuelto se almacena en STP y S.

5

Estás viendo asignación encadenada.

Es lo mismo que:

Solver *S; 
Solver *STP; 
S = UseDummySolver ? createDummySolver() : new STPSolver(true); 
STP = S; 
+0

@sixlettervariables Sí, lo arreglé, lo siento, C++ no es mi fuerte. – NominSim

+0

El tiempo lo es todo :) +1 también – houbysoft

+1

@sixlettervariables, NominSim, edité la respuesta y puse la desreferencia incorrecta. Lo siento por eso; el código original me confundió. No es culpa de NominSim en absoluto. – steveha

6

Recomendaría este:

Solver *S = UseDummySolver ? createDummySolver() : new STPSolver(true); 
Solver *STP = S; 

Es conciso, pero limpio y ordenado.

También, se utiliza inicialización, en lugar de asignación. Debería preferir la inicialización sobre la asignación siempre que sea posible.

+1

Te di un +1 para la recomendación de inicialización vs asignación :) – houbysoft

0

yo preferiría bien esto:

std::unique_ptr<Solver> S ( UseDummySolver 
            ? createDummySolver() 
            : new STPSolver(true) ); 
Solver& STP = *S; 

o esto:

std::shared_ptr<Solver> S ( UseDummySolver 
            ? createDummySolver() 
            : new STPSolver(true) ); 
std::shared_ptr<Solver> STP = S; 

Tanto evitar un problema con el código que tienes ahí: no necesitamos decidir qué hacer puntero llama al delete cuando los objetos abandonan el alcance (o, de hecho, recuerda la necesidad de llamar al delete). En su lugar, solo esperamos hasta que las variables salgan del alcance, entonces el objeto Solver se elimina automáticamente. STP es en el primer caso inequívocamente otra forma de acceder al objeto mientras está dentro del alcance, en el segundo caso es un "copropietario" independiente del objeto y ambos punteros pueden reasignarse de forma independiente.