2009-12-02 16 views
6

Me gustaría pasar un puntero por referencia a una función, de modo que realmente puedo cambiar la dirección a la que apunta el puntero pasado y me gustaría asignar este argumento por defecto valor.C++ Pase el puntero por referencia y asigne el valor predeterminado

algo como esto:

en la declaración

void myFunc(SomeType* &var=NULL); 

y la definición:

void MyClass::myFunc(SomeType* &var){ 
    if(var!=NULL) 
     (*var)=(*someOtherPointer); 

    if(someCondition) 
     var=NULL; 
} 

tal manera que un usuario llamado puede decidir si quiere llamar a la función con un argumento o sin argumento Y sucht que si decide pasar un argumento, y somecondition sostiene, el puntero pasado apuntará a NULL después

sin embargo - si trato de hacerlo de esta manera puedo obtener un:

error C2440: 'default argumento ':' int 'no puede ser enviado a' SomeType * & '

¡Gracias por la ayuda!

Respuesta

7

El mensaje de error lo dice todo: está pasando un entero en lugar de una referencia-a-un-puntero-a-SomeType. Para hacer lo que quiere, se puede utilizar un puntero a un puntero a SomeType:

void myFunc(SomeType** var=NULL); 

void MyClass::myFunc(SomeType** var){ 
    if(var!=NULL && *var!=NULL) 
     (**var)=(*someOtherPointer); 

    if(var!=NULL && someCondition) 
     *var=NULL; 
} 
+0

A menos que "someCondition" incluya "var! = NULL", acaba de aceptar una respuesta que quita referencias a un puntero NULL. Probablemente no sea lo que querías. – imaginaryboy

+0

Además, tenga en cuenta que el uso (** var) = (* someOtherPointer) realmente hará una copia de objeto. Si solo pretendía hacer una copia de puntero, probablemente querría (* var) = (algún otro puntero). – Thought

14

NULL no es un lvalue - no se puede pasar por referencia. Sería como pasar 4 a una función que espera un int&.

La parte 'int' se debe a que NULL es un macrodefinido 0.

Su mejor opción sería utilizar un puntero para pasar el puntero por referencia, es decir, un puntero doble. Entonces, si el parámetro es NULL, no pasó nada. Si no, es la dirección del puntero que debe modificarse [para apuntar a NULL si se cumple alguna condición].

+0

+1 Has acertado tan rápido;) – AraK

+0

insomnia be damned. – aib

+1

Otra opción sería usar boost :: optional (sin juego de palabras) –

2

También puede considerar el uso de impulso :: opcional (no el código más simple que se puede utilizar, pero la opción es allí):

void f(boost::optional<int&> r = boost::optional<int&>()) 
{ 
    if (r) *r = 5; 
} 
int main() 
{ 
    int x = 0; 
    f(x); std::cout << x << std::endl; // 5, it did change the value 
    f(); // compiler will default to an empty optional<int&> object 
} 
+0

+1 para el ejemplo. –

2

Ok, puedo ver por qué te gustaría hacer esto desde la perspectiva de ejercer el cerebro C++, pero ¿de verdad hacer que en el código de producción? Parece una técnica increíblemente brumosa con efectos secundarios, cuando se mira el código como un colega 1 año después. ¿Pensaste en usar dos funciones separadas con nombres claros, una que devuelve un puntero y otra que realiza cualquier otro trabajo necesario?

2

¿Por qué no sobrecargar la función?

void myFunc() { 
    //whatever logic should happen if a null pointer is passed in 
} 

void myFunc(SomeType* &var) { 
    if(var!=NULL) { 
    (*var)=(*someOtherPointer); 
    } 

    if(someCondition) { 
     var=NULL; 
    } 
} 
Cuestiones relacionadas