¿Se eliminaría "if ... ASSERT" en la versión de lanzamiento?

Sometimes I write code like

if (ptr)
    ASSERT(ptr->member);

en lugar de

ASSERT(!ptr || ptr->member);

because it's more straightforward IMO. Would the redundant comparison remain in the release build?

preguntado el 08 de noviembre de 11 a las 15:11

There's one way to find out... compile it and see. -

no, all code in the ASSERT will be trimmed. -

We know the code in the assertion would be removed, @Max. The question asks whether the comparison antes de it would also be removed. -

An optimizing compiler would easily eliminate the if, so long as it wasn't perceived as having a side-effect. -

3 Respuestas

I'd say that depends on your compiler.

In release mode, the ASSERT macro won't evaluate ptr->member and will resolve to a trivial expression that the compiler will optimize out, but the if statement and the associated comparison will remain as is.

However, if the compiler is smart enough to determine that the condition does not have any side effect, it might optimize the entire if statement away. Compiling to assembly (using the /FA option) would give you a definite answer.

respondido 08 nov., 11:20

Surely modern compilers would optimise out if() (void)0; or similarly pointless operation? Or maybe I'm overly optimistic. - jbat100

@jbat100: They certainly should, but there's only one way to be sure. - Mike Seymour

@jbat100, it depends on the conditional expression. Working from the questioner's example, ptr might be an instance of a class that overrides operator bool() with a function that has side effects. If that's the case, the conditional expression cannot be elided, as the program's behavior would change. - Frédéric Hamidi

As long as the compiler is not stupid, yes it would be trimmed.

Try writing this in the compiler:

if (x);

It gives you a warning that statement has no effect and like I said, if it is not stupid, it would remove the code.

If you want to be sure, you could compile it with your compiler and see the assembly.

respondido 08 nov., 11:20

LLVM removes it when optimization is required (by the user):

int main(int argc, char **argv) {
  if (argc) {}
  return 0;
}

Se convierte en:

define i32 @main(i32 %argc, i8** nocapture %argv) nounwind readnone {
  ret i32 0
}

respondido 08 nov., 11:20

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.