web-dev-qa-db-ja.com

Pedantic gcc警告:関数の戻り型の型修飾子

GCC 4.3でC++コードを初めてコンパイルしたとき(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は不要だと思いますが、それを使用して警告を生成する必要がある理由を理解するのに苦労しています。 constを省略すべき他の場所はありますか?

66
Seth Johnson

標準に違反していません。 warningsではなくerrorsである理由です。

そして確かにあなたは正しいです-主要なconstは不要です。コンパイラは、他の状況では何か意味があるかもしれないコードを追加したので警告しますが、この状況では何も意味がなく、戻り値が結局変更可能になったときに失望しないようにしたいのです。

91
Rob Kennedy

Boost.ProgramOptionsを使用するコードをコンパイルするときにこの警告が発生しました。私が使う -Werrorそのため、警告はビルドを殺していましたが、警告の原因はBoostの深部にあったため、コードを変更してもそれを取り除くことはできませんでした。

掘り下げた後、警告を無効にするコンパイラオプションを見つけました。

-Wno-ignored-qualifiers

お役に立てれば。

19
ccaughie

呼び出し元は参照された(ポイントされた)値を変更できるため、定数値を返すのは、参照またはポインター(この場合は定数ポインターではなく定数へのポインター)を返す場合にのみ意味があります。

あなたの質問に関係のないコードに関する別のコメント:代わりにセッターを使用する方が良いと思います

int& getNonconstReference() {
    return _myInt;
}

どちらにする必要があります:

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

さらに、intへのconst参照を返すことは役に立ちません。コピーまたは移動がより高価な大きなオブジェクトには意味があります。

4
Brahim

これを持っている

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 ++は分類子を無視することについて警告しますが、無視しません。警告は、コピーを取り、コピーのconst分類子を無視するユーザーに関するものだと思います。しかし、これは絶対に正しい動作であるため、警告ではありません。そして、これを行うのは理にかなっています。

2
mcbulba

-pedanticはISO標準への厳密な順守のみを許可すべきではありませんか?もちろん-std =に依存します...

1
Steve

この警告は、変更すべきではないオブジェクトへのポインタを返す関数を宣言する際の混乱を避けるためにも役立ちます。

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

// correct:
const Foo* bar();
1
Luchs

無視される基本型の結果の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に関する警告が表示されることもあります。どんな小さな利点でも構想するのにかなり厳しい費用がかかります。