2012-03-19 3 views
-3

J'écris une méthode en retournant un double*. Cependant, je voudrais baser un autre comportement de méthode sur la sortie de cette méthode. Je voudrais avoirC++ - tester un pointeur

if (methodReturningArray()==0) 
{ 
    this_behavior(); 
} 
else 
{ 
    this_other_behavior(methodReturningArray()); 
} 

Est-il approprié alors d'avoir methodReturningArray() retour soit le « initialisé » ou « construire » double* et si ce double* ne pouvait pas être convenablement être initialisés ou de construire, de retour comme ça

double* new_array ; 
return new_array ; 

? En d'autres termes, la sortie double* joue également le rôle d'un booléen pour vérifier si certaines propriétés sont terminées afin que la sortie double* puisse être générée.

Merci et salutations.

+4

Je ne vois pas question ici, quelqu'un pourrait-il * Point * moi ce? – Griwes

+0

Est-ce ... [?], Oubliez le? . Des excuses. – octoback

+0

C'est plus que nous ne savons pas ce que vous demandez. Votre question est libellée étrangement, et nous ne savons pas ce que vous voulez aider. Pouvez-vous le reformuler? – user1118321

Répondre

1

Pour indiquer que quelque chose que vous retournez par pointeur n'a pas été initialisé, utilisez return NULL. Et vérifiez avec if(double* d = method()) (ou de toute autre manière que vous aimez).

Cependant, ce n'est pas votre (ou mon) grand-père C++ et vous ne devriez écrire quelque chose comme ça, quand vous avez absolument raison de le faire. Je préférerais renvoyer un std::array ou std::vector par valeur enveloppée et lancer une exception si le comportement qui conduit à l'échec d'initialisation est en quelque sorte exceptionnel. Si l'échec de l'initialisation fait partie de l'idée, j'envelopperais la valeur de retour dans un boost::optional. Mais probablement j'écrirais quelque chose qui prend un OutputIterator pour ne pas forcer un conteneur particulier sur mon client. Notes sur le désastre: double* d; return d laissera votre client avec un pointeur qui pointe vers la mémoire aléatoire. Il n'y a aucun moyen pour elle de savoir si elle doit être deleted[] ou si elle est valide. Toujours initialiser vos pointeurs.

extraits de code:

// outputiterator 
template<typename OutputIterator> 
void myFunc(OutputIterator o) { 
    // fill stuff in 
    if(someThing) { 
    for(int i = 0; i < 5; ++i) 
    { 
     *o++ = 23; 
    } 
    } else { 
    // leave it empty 
    } 
} 

// client calls like: 
std::vector<double> v; 
myFunc(std::back_inserter(v)); 
if(!v.empty()) { 

} else { 

} 

// exception 
std::vector<double> myFunc() { 
    std::vector<double> v; 
    if(someThing) { v.push_back(23); return v; } 
    else throw std::runtime_error("Nargh!"); 
} 

// client 
try { 
    auto v = myFunc(); 
} catch(std::runtime_error err) { 

} 

// optional 
boost::optional<std::vector<double>> 
myFunc() { 
    std::vector<double> v; 
    if(someThing) { v.push_back(23); return v; } 
    else return boost::optional< std::vector<double> >(); 
} 

//client 
auto v = myFunc(); 
if(v) { 

} else { 

} 
+0

Je ne suis pas d'accord; il n'y a absolument aucune raison d'utiliser des wrappers stupides ou même Boost dans de tels cas, il ne fait que convoluer votre code, le rend plus verbeux et compile plus lentement en le modélisant davantage (surtout sous gcc qui n'est pas très rapide quand il s'agit de template) ou même EH qui ajoute juste des tonnes d'exécution inutile et de magie noire en se déroulant. – q66

+1

@ q66 'optionnel' n'est certainement pas ce qui va trop nuire à vos temps de compilation et il n'est pas trop verbeux. Je préférerais ne pas avoir '' supprimer '' des choses que d'autres 'new' et vous avez aussi des problèmes dès que vous avez besoin de changer l'allocateur avec des choses écrites comme ça. Mais cet argument est vraiment trop long et a été pensé assez souvent. Il y a du mérite des deux côtés et c'est une question de vos objectifs. – pmr

+0

en fait, y compris presque tout composant Boost va nuire à vos temps de compilation, comme Boost est bourré d'interdépendances, donc il doit développer beaucoup de code. Je ne pense pas vraiment que ce soit un avantage réel. Quant à la suppression, c'est très bien dans la plupart des cas. Je peux voir une utilisation pour le refcounting dans plusieurs cas où la manipulation manuelle est susceptible d'être sujette aux erreurs, mais c'est rare. – q66

0

Vous avez trois façons, fondamentalement.

1) En cas d'erreur, retournez la valeur NULL. Ensuite, vous pouvez faire des vérifications booléennes sans problème, et c'est suffisant dans la plupart des cas.

2) booléen de retour, et gérer la sortie double * en utilisant une référence ou un argument de pointeur comme ceci:

bool methodReturningArray(double **out) { *out = ...; return true; } 

double *out; 
if (!methodReturningArray(&out)) this_other_behavior(out); else .... 

3) Lancer une exception - l'OMI un peu alambiquée et unuseful.

Le renvoi d'un pointeur non initialisé ne vous permettra pas d'effectuer une évaluation booléenne sur celui-ci, et il est dangereux, car un tel pointeur sera supposé être un pointeur qui suit.

+0

Je pense vraiment qu'il y a de meilleures idiomes en C++ pour gérer de telles situations maintenant ('boost :: optional', return by value). – pmr

+0

@pmr, je ne pense pas vraiment, il n'y a pratiquement aucun avantage à le faire, et je peux penser à plusieurs inconvénients. Je ne suis pas très friand du style C++ "moderne", IMO ça complique juste les choses pour absolument aucune raison. – q66

+0

Si vous pensez que c'est pour "aucune raison", jetez un œil aux bugs dans la catégorie "array and string handling" ici: http://www.viva64.com/en/0079/. * Tous * sont causés par l'absence de style C++ "moderne". Personnellement, je trouve cela embarrassant: nous, programmeurs, faisons encore les erreurs d'il y a 30 ans aujourd'hui. Pray tell, comment l'utilisateur de ce code connaitra-t-il la taille du tableau pointé par le pointeur? Vous pouvez prétendre que vous n'aimez pas et n'avez pas besoin de tout ce que vous voulez, mais vous ne pouvez pas prétendre que c'est pour "aucune raison". –