c++ - tutorial - ¿Existe una opción de GCC para advertir sobre escribir `this-field` en lugar de` this-> field`?
netbeans c++ descargar (4)
El siguiente código (que contiene un error vicioso) se compila con GCC sin previo aviso. Pero, por supuesto, no funciona como lo esperaba el desarrollador (yo).
#include <iostream>
struct A
{
bool b;
void set(bool b_) { this->b = b_; }
bool get() const { return this-b; } // The bug is here: ''-'' instead of ''->''
};
int main()
{
A a;
a.set(true);
std::cout << a.get() << std::endl; // Print 1
a.set(false);
std::cout << a.get() << std::endl; // Print 1 too...
return 0;
}
¿Qué advertencia puedo agregar para el compilador (GCC 4.8) para evitar este tipo de error tipográfico?
Pregunta vinculada: ¿Hay alguna opción para forzar (o advertir) el acceso a las variables / funciones miembro con
this->
?
Este problema en particular es detectado por
cppcheck
:
$ cppcheck --enable=all this-minus-bool.cxx Checking this-minus-bool.cxx... [this-minus-bool.cxx:7]: (warning) Suspicious pointer subtraction. Did you intend to write ''->''? (information) Cppcheck cannot find all the include files (use --check-config for details)
Esto fue sin ruta de inclusión dada.
Si agrego
-I /usr/include/c++/4.8/
, el problema aún se detecta:
Checking this-minus-bool.cxx... [this-minus-bool.cxx]: (information) Too many #ifdef configurations - cppcheck only checks 12 of 45 configurations. Use --force to check all configurations. [this-minus-bool.cxx:7]: (warning) Suspicious pointer subtraction. Did you intend to write ''->''? [/usr/include/c++/4.8/bits/ostream.tcc:335]: (style) Struct ''__ptr_guard'' has a constructor with 1 argument that is not explicit. [/usr/include/c++/4.8/bits/locale_classes.tcc:248]: (error) Deallocating a deallocated pointer: __c
y luego cppcheck funciona lentamente a través de las configuraciones
#ifdef
mencionadas
#ifdef
.
(Como nota al margen, el error en
local_classes.tcc
es un falso positivo, pero es muy difícil saberlo para una herramienta automatizada, ya que sería necesario tener en cuenta que el bloque
catch
en este sitio no debe ingresarse cuando la macro
__EXCEPTIONS
está desarmado)
Descargo de responsabilidad: no tengo otra experiencia con cppcheck.
Me gustaría sugerir otra herramienta (además de
cppcheck
propuesta por @ arne-vogel), que ofrece una mejor ayuda visual en lugar de la advertencia solicitada:
Use
clang-format
automáticamente su código.
El resultado podría verse así (dependiendo de la configuración), haciendo que el error sea más visible por los espacios agregados alrededor del
operator-
:
struct A {
bool b;
void set(bool b_) { this->b = b_; }
bool get() const { return this - b; }
};
No,
this - b
realiza
aritmética de puntero
en el puntero, a pesar de que
b
es un tipo
bool
(
b
se convierte implícitamente en
int
).
(Curiosamente,
siempre
puede establecer
this + b
en un puntero donde
b
es un tipo
bool
, ¡ya que puede establecer un puntero en uno más allá del final de un escalar! Así que incluso su observador de
comportamiento indefinido
favorito lo permitiría).
La comprobación de límites de matriz siempre ha sido el trabajo de un programador de C ++.
Tenga en cuenta también que en sus casos el uso de
this
es superfluo: por lo tanto, reducir este uso excesivo es una forma de hacer que el problema desaparezca.
No, no hay forma de recibir una advertencia. Las conversiones implícitas, aunque perversas, están permitidas por el lenguaje.
Sin embargo, en este caso de uso específico podemos hacerlo mejor: envolviendo el bool en una clase de contenedor que tiene conversiones explícitas y no hay operaciones aritméticas definidas.
Esto da como resultado un error del compilador cuando se usa incorrectamente lógicamente, lo que normalmente se considera preferible a una advertencia si el objetivo es la corrección lógica.
Es interesante notar que c ++ 17 desprecia
bool::operator++
ya que esta aritmética se considera malvada.
ejemplo:
struct Bool
{
explicit Bool(bool b) : value_(b) {}
explicit operator bool() const { return value_; }
private:
bool value_;
// define only the operators you actually want
friend std::ostream& operator<<(std::ostream& os, const Bool& b) {
return os << b;
}
};
struct X
{
bool foo() {
// compilation failure - no arithemetic operators defined.
// return bool(this-b);
// explicit conversion is fine
return bool(b);
}
Bool b { true }; // explicit initialisation fine
};