Pedantic gcc警告:函数返回类型上的类型限定符

95

当我首次使用GCC 4.3编译我的C++代码时(在使用-Wall -Wextra选项成功编译过4.1、4.0和3.4版本后),我突然遇到了很多形如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吗?


请参考以下类似的问题和答案:https://dev59.com/uXI-5IYBdhLWcg3w8NOB - Johannes Schaub - litb
24
我以前见过这样的警告,但还是花了好几分钟试图理解我的代码出了什么问题。也许更好的错误报告可以加快处理速度。比如说,不要显示“warning: type qualifiers ignored on function return type”,而应该显示“warning: 当你返回值时,请不要添加const限定符”。 - Avio
@Avio 为什么我们不应该在返回值的函数中添加 const 限定符?这是因为我们不希望该值在之后被更改。 - Franky
@Franky const int foo(); <- const 是无用的。完全没有作用。const int & foo(); <- const 是有意义的。 - jonesmz
8个回答

118

这并不违反标准。这就是为什么它们被称为“警告”,而不是“错误”。

事实上,你是正确的 - 前置的const是多余的。编译器发出警告是因为你添加了其他情况下可能有意义但在此情况下毫无意义的代码,并且它希望确保你以后不会失望,当你的返回值最终是可修改时。


26
警告和错误的区别并不代表什么。像 sizeof(void) 这样的其他无效代码仅仅是发出警告,但显然是被禁止的。标准并不知道警告和错误之间的区别:它们都是诊断信息。 - Johannes Schaub - litb
3
他说的仍然是正确的。当然,它们是警告并不保证不会像你所说的那样违反标准,但它们被作为警告而不是错误的原因是编译器实现者不希望禁止它。他们不想禁止它的原因是因为它不违反标准。 - jalf
1
它是否完全违反了标准? - Philipp
1
我认为我的第一句话已经很清楚了,@Philipp。请看Johannes在问题评论中提到的问题:为什么返回类型上的类型限定符是无意义的? - Rob Kennedy

23

在编译使用Boost.ProgramOptions的代码时,我遇到了这个警告。我使用-Werror使得警告将导致我的构建失败,但由于警告的源代码深藏在Boost中,所以无法通过修改我的代码来消除它。

经过长时间的挖掘,我找到了一个编译器选项可以禁用这个警告:

-Wno-ignored-qualifiers
希望这可以帮助到你。

9
我也遇到了同样的问题,最终我将Boost的包含路径设置为-isystem而不是-I,这样可以抑制Boost头文件引发的所有警告。 - Philipp
3
@Philipp的解决方案是正确的。使用-Wno-ignored-qualifiers会影响您的代码,并防止编译器发出您创建的警告,而Philipp的解决方案不会影响由您自己的代码产生的警告。 - Wond3rBoi

8

只有在返回引用或指针时才有意义返回常量值(在这种情况下是指向常量的指针而不是常量指针),因为调用者能够修改所引用(指向)的值。

与您的问题无关的代码另一个注释: 我认为最好使用setter而不是

int& getNonconstReference() {
    return _myInt;
}

应该选择哪个呢:

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

此外,对于返回一个int类型的const引用是没有意义的。但对于一个更大的对象,其复制或移动更加昂贵,返回const引用则是有意义的。

2

有这样一个例子:

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正确性不是要让人们难以做错吗?并且由于人们尝试错误的事情,期望返回类型应该声明为const。

此外,g++会警告忽略分类器,但实际上并没有忽略它。我认为,这个警告是针对那些复制并忽略其副本上的const分类器的用户。但这不应该是一个警告,因为这是绝对正确的行为。这样做是有意义的。


3
如果你添加了一个“const”,G++ 将不会发出警告。对于非类类型的返回值,const 限定符是被忽略的。 - Philipp

1

-pedantic不应该只允许严格遵守ISO标准吗?当然,这取决于-std=...


1
这个警告也有助于避免在声明返回指向不应被修改的对象的指针的函数时产生混淆:
// "warning: type qualifiers ignored on function return type"
// as the pointer is copied. 
Foo* const bar();

// correct:
const Foo* bar();

0

在基本类型结果上,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也会很好,因为它会禁止移动语义;这对于所预想的任何微小优势来说都是相当严重的代价。


-5

Scott Meyers指出,有很充分的理由让某人返回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关键字的话。

16
不,它不应该编译通过。some_calculation的结果是一个int类型的rvalue(右值)。您不能将非类类型的rvalue进行赋值操作。 - CB Bailey
1
如果返回值是类类型,则const是正确的,不会生成警告。 - Philipp
你实际上尝试编译过这个例子吗?GCC会报错:"error: lvalue required as left operand of assignment",clang++会报错:"error: expression is not assignable"。 - Bulletmagnet
他可能是指 == - user1032677

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接