Je pense que c'est une expression qui évalue à une valeur par défaut pour un type cleanup_t. En d'autres termes, une expression qui renvoie un pointeur NULL à une fonction qui renvoie void.
en C/C++, expressions sans effets secondaires (qui c'est - je pense) sont des déclarations valides, comme vous pouvez avoir une déclaration comme:
1 + 2;
Ce n'est pas une erreur de syntaxe, mais certains les compilateurs pourraient donner un avertissement. Ils ne donnent pas souvent un avertissement pour les expressions sans effet secondaire qui renvoient des valeurs NULL ou sont simplement des noms de variables parce que ce type d'expression est souvent utilisé dans les macros à des fins de débogage (comme la macro assert()).
Vous pouvez l'imaginer comme appelant le constructeur par défaut pour le type cleanup_t
. Cette syntaxe de type constructeur par défaut pour les types prédéfinis (ou leur typedef) a été ajoutée à C++ afin que les templates puissent définir les éléments du type transmis comme paramètre de template aux valeurs par défaut tout en permettant au paramètre type de template d'être type non défini par l'utilisateur. Il pourrait y avoir d'autres raisons, mais je crois que c'est l'un d'entre eux.
Quelque chose comme:
template <class T>
class foo
{
T myT;
public:
foo() {
myT = T();
};
};
typedef void (*cleanup_t)();
class bar
{
};
int not_quite_a_cleanup_t_func()
{
return 1;
}
int main()
{
foo<int> intFoo;
foo<cleanup_t> cleanup_t_foo;
foo<bar> barFoo;
// here I'm going to harp on one of the things I don't like about C++:
//
// That so many things that look like function calls are not or that
// the parens cause subtle behavior changes.
//
// I believe this is the reason this question was posted to
// stackoverflow, so it's not too far off topic.
//
// Many of these things exist because of backwards compatibility with C or
// because they wanted to fit in new features without adding keywords or
// new reserved tokens or making the parser even more complex than it already
// is. So there are probably good rationales for them.
//
// But I find it confusing more often than not, and the fact that there
// might be a rationale for it doesn't mean I have to like it...
cleanup_t cleanup1(); // declares a function named cleanup1 that returns a cleanup_t
cleanup_t cleanup2 = cleanup_t(); // cleanup2 is a variable of type cleanup_t that
// is default initialized
cleanup_t* cleanup3 = new cleanup_t; // cleanup3 is a pointer to type cleanup_t that
// is initialized to point to memory that is
// *not* initialized
cleanup_t* cleanup4 = new cleanup_t(); // cleanup4 is a pointer to type cleanup_t that
// is initialized to point to memory that *is*
// initialized (using default intialization)
cleanup2 = cleanup_t(not_quite_a_cleanup_t_func); // explicit type conversion using functional notation
cleanup_t(); // the OP's problem
cleanup2(); // call the function pointed to by cleanup2
(*cleanup2)(); // same thing
class cleanup_class
{
cleanup_t cleanup5;
public:
cleanup_class() :
cleanup5() // class member default initialization
{ };
};
}