Pedantic gcc warning: квалификаторы типа для типа возврата функции - PullRequest
66 голосов
/ 16 июля 2009

Когда я впервые скомпилировал свой код C ++ с GCC 4.3 (после успешной компиляции без предупреждений на 4.1, 4.0, 3.4 с параметрами -Wall -Wextra) я внезапно получил кучу ошибок вида warning: type qualifiers ignored on function return type.

Рассмотрим temp.cpp:

class Something
{
public:
    const int getConstThing() const {
        return _cMyInt;
    }
    const int getNonconstThing() const {
        return _myInt;
    }

    const int& getConstReference() const {
        return _myInt;
    }
    int& getNonconstReference() {
        return _myInt;
    }

    void setInt(const int newValue) {
        _myInt = newValue;
    }

    Something() : _cMyInt( 3 ) {
        _myInt = 2;
    }
private:
    const int _cMyInt;
    int _myInt;
};

Бег g++ temp.cpp -Wextra -c -o blah.o:

temp.cpp:4: warning: type qualifiers ignored on function return type
temp.cpp:7: warning: type qualifiers ignored on function return type

Может кто-нибудь сказать мне, что я делаю неправильно, что нарушает стандарт C ++? Я полагаю, что при возврате по значению ведущий const является излишним, но у меня возникают проблемы с пониманием, почему с ним необходимо создать предупреждение. Есть ли другие места, где я должен был бы остановиться?

Ответы [ 8 ]

91 голосов
/ 16 июля 2009

Это не нарушает стандарт. Вот почему они предупреждения , а не ошибки .

И действительно, вы правы - ведущий const лишний. Компилятор предупреждает вас, потому что вы добавили код, который в других обстоятельствах может что-то значить, но в этом случае ничего не значит, и он хочет убедиться, что вы не будете разочарованы позже, когда ваши возвращаемые значения окажутся изменяемыми в конце концов.

19 голосов
/ 19 августа 2009

Я столкнулся с этим предупреждением при компиляции кода, который использует Boost.ProgramOptions. Я использую -Werror, поэтому предупреждение убивало мою сборку, но поскольку источник предупреждения был в глубине Boost, я не мог избавиться от него, изменив свой код.

После долгих копаний я нашел опцию компилятора, которая отключает предупреждение:

-Wno-ignored-qualifiers

Надеюсь, это поможет.

4 голосов
/ 19 мая 2015

Возвращение постоянного значения имеет смысл, только когда вы возвращаете ссылку или указатель (в данном случае указатель на константу, а не постоянный указатель), поскольку вызывающая сторона может изменять ссылочное (указываемое) значение.

Еще один комментарий к коду, не связанный с вашим вопросом: Я думаю, что лучше использовать сеттер вместо

int& getNonconstReference() {
    return _myInt;
}

Что будет:

void setMyInt(int n) {
  _myInt = n;
}

Более того, бесполезно возвращать константную ссылку на int. Это имеет смысл для более крупного объекта, чья копия или перемещение дороже.

2 голосов
/ 13 июля 2010

Имея это

struct Foo { Foo(int) {} operator bool() { return true; } };

и тот

Foo some_calculation(int a, int b) { Foo result(a + b); /*...*/ return result; }

пример

if (some_calculation(3, 20) = 40) { /*...*/ }

компилируется без предупреждения. Конечно, это редко. Но разве это не правильность того, что людям трудно делать что-то неправильно? И с ожиданием, что люди попробуют что-то неправильное, тип возвращаемого значения должен быть объявлен как const. И: g ++ предупреждает о игнорировании классификатора, но не игнорирует его. Я думаю, что предупреждение касается пользователей, которые берут копию и игнорируют константные классификаторы в своей копии. Но это не должно быть предупреждением, потому что это абсолютно правильное поведение. И это имеет смысл сделать.

1 голос
/ 07 апреля 2014

Это предупреждение также полезно, чтобы избежать путаницы при объявлении функций, возвращающих указатели на объекты, которые не должны быть изменены:

// "warning: type qualifiers ignored on function return type"
// as the pointer is copied. 
Foo* const bar();

// correct:
const Foo* bar();
1 голос
/ 14 февраля 2011

Разве -педантика не должна позволять строго соблюдать стандарт ISO? В зависимости от -std = конечно ...

0 голосов
/ 29 марта 2016

Существует разница между const для результата базового типа, где он игнорируется, и const для результата типа класса, где он обычно приводит к хаосу.

namespace i {
    auto f() -> int const { return 42; }
    void g( int&& ) {}
}

namespace s {
    struct S {};
    auto f() -> S const { return {}; }
    auto g( S&&  ) {}
}

auto main() -> int
{
    { using namespace i; g( f() ); }    // OK
    { using namespace s; g( f() ); }    // !The `const` prevents this.
}

Вот почему компилятор предупреждает в первом случае: это особый случай, который может не выполнять то, что можно было ожидать наивно.

Для современного программирования ИМХО было бы неплохо также с предупреждением о const о результате типа класса, так как он запрещает семантику перемещения; довольно серьезная цена за любое небольшое преимущество, которое только можно себе представить.

0 голосов
/ 20 апреля 2010

Скотт Мейерс указал, что есть довольно веская причина, почему кто-то захочет вернуть const значения. Вот пример:

int some_calculation(int a, int b) { int res = 0; /* ... */ return res; }

/* Test if the result of the calculation equals 40.*/
if (some_calculation(3,20) = 40)
{

}

Ты видишь, что я сделал не так? Этот код абсолютно правильный и должен компилироваться. Проблема в том, что компилятор не понял, что вы намеревались сравнить вместо присвоения значения 40.

С возвращаемым значением const приведенный выше пример не скомпилируется. Ну, по крайней мере, если компилятор не отбрасывает ключевое слово const.

...