Этот после кода (содержащий порочную ошибку) компилирует с GCC без любого предупреждения. Но, конечно, это не работает как ожидалось разработчиком (меня).
#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;
}
Какое предупреждение я могу добавить, чтобы компилятор (GCC 4.8) избежал этого вида опечатки?
Связанный вопрос: Есть ли любая опция вызвать (или предупредить) доступ к членским переменным/функциям с this->
?
Эта конкретная проблема обнаруживается 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)
Это было без, включают данный путь. Если я добавляю -I /usr/include/c++/4.8/
, проблема все еще обнаруживается:
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
и затем cppcheck медленно работает через вышеупомянутое #ifdef
конфигурации.
(Как примечание стороны, ошибка в local_classes.tcc
является положительной ложью, но это очень трудно сказать для автоматизированного инструмента, поскольку это должно было бы знать, что catch
блок на этом сайте не должен быть введен, когда макрос __EXCEPTIONS
сброшен.)
Правовая оговорка: у Меня нет никакого другого опыта с cppcheck.
Нет, this - b
работает адресная арифметика с указателями на указателе this
, несмотря на b
являющийся bool
тип (b
неявно преобразовывается в int
).
(Интересно, Вы можете всегда , устанавливает this + b
на указатель, где b
bool
тип, так как можно установить указатель на одно прошлое конец скаляра! Таким образом, даже Ваш фаворит неопределенное поведение сыщик разрешил бы что один.)
проверка границ Массива всегда была заданием программиста на C++.
Примечание также, что в Ваших случаях использование this
является лишним: так сокращение этого чрезмерного использования является одним способом заставить проблему уйти.
Нет, нет никакого способа получить предупреждение. Неявные преобразования, хотя извращенный, позволяются языком.
Однако в этом определенном варианте использования мы можем добиться большего успеха - путем обертывания bool в класс обертки, который имеет явные преобразования и никакие определенные арифметические операции.
Это приводит к ошибке компилятора, когда логически неправильно используется, которая обычно рассматривается как предпочтительная для предупреждения, если логическая правильность является целью.
интересно отметить, что C++ 17 удерживает от использования bool::operator++
, поскольку эта арифметика рассматривается как зло.
пример:
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
};
Я хотел бы предложить другой инструмент (кроме cppcheck
предложенный @arne-vogel), давая лучшую визуальную помощь вместо предупреждения, относительно которого попросили:
Использование формат лязга для автоматического форматирования кода. Результат мог бы быть похожим на это (в зависимости от настроек), делая ошибку более видимой пробелами добавленный приблизительно operator-
:
struct A {
bool b;
void set(bool b_) { this->b = b_; }
bool get() const { return this - b; }
};