迂腐的 gcc 警告:函数返回类型上的类型限定符
当我第一次使用 GCC 4.3 编译 C++ 代码时(使用 -Wall -Wextra
选项在 4.1、4.0、3.4 上成功编译后没有警告)我突然得到了一堆形式为警告:函数返回类型上忽略类型限定符
的错误。
考虑 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 吗?
When I compiled my C++ code with GCC 4.3 for the first time, (after having compiled it successfully with no warnings on 4.1, 4.0, 3.4 with the -Wall -Wextra
options) I suddenly got a bunch of errors of the form warning: type qualifiers ignored on function return type
.
Consider 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;
};
Running 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
Can someone tell me what I am doing wrong that violates the C++ standard? I suppose that when returning by value, the leading const
is superfluous, but I'm having trouble understanding why it's necessary to generate a warning with it. Are there other places where I should leave off the const?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
它并不违反标准。 这就是为什么它们是警告而不是错误。
事实上,你是对的 - 领先的 const 是多余的。 编译器会向您发出警告,因为您添加的代码在其他情况下可能有意义,但在这种情况下毫无意义,并且它希望确保您稍后在返回值可修改时不会感到失望。
It doesn't violate the standard. That's why they're warnings and not errors.
And indeed you're right — the leading
const
is superfluous. The compiler warns you because you've added code that in other circumstances might mean something, but in this circumstance means nothing, and it wants to make sure you won't be disappointed later when your return values turn out to be modifiable after all.我在编译一些使用 Boost.ProgramOptions 的代码时遇到了这个警告。 我使用
-Werror
因此警告会终止我的构建,但由于警告的来源位于 Boost 的深处,我无法通过修改代码来摆脱它。经过大量挖掘后,我找到了禁用警告的编译器选项:
希望这会有所帮助。
I encountered this warning when compiling some code that uses Boost.ProgramOptions. I use
-Werror
so the warning was killing my build, but because the source of the warning was in the depths of Boost I couldn't get rid of it by modifying my code.After much digging I found the compiler option that disables the warning:
Hope this helps.
仅当返回引用或指针(在本例中是指向常量的指针而不是常量指针)时,返回常量值才有意义,因为调用者能够修改引用(指向)的值。
对代码的另一条评论与您的问题无关:
我认为最好使用 setter 而不是
Which will should be:
此外,返回对 int 的 const 引用是没有用的。 对于复制或移动成本更高的较大对象来说,这确实有意义。
Returning a constant value only makes sense when you return a reference or a pointer(in this case pointer to constant and not a constant pointer) because the caller is able to modify the referenced (pointed to) value.
Another comment on the code not related to your question:
I think it's better to use a setter instead of
Which will should be:
Moreover, it's useless to return a const reference to an int. It does make sense for a bigger object whose copy or move is more expensive.
有了这个
struct Foo { Foo(int) {} operator bool() { return true; } } };
以及
Foo some_calculation(int a, int b) { Foo result(a + b); /*...*/ 返回结果; }
示例
if (some_calculation(3, 20) = 40) { /*...*/ }
编译时不会出现警告。 当然,这种情况很少见。 但是 const 正确性不就是让人们很难做错事吗? 由于期望人们尝试一些错误的事情,因此返回类型应该声明为 const。
并且:g++ 警告忽略分类器,但不会忽略它。 我认为,警告是关于获取副本并忽略副本上的 const 分类器的用户。 但这不应该是一个警告,因为这是绝对正确的行为。 这样做是有道理的。
Having this
struct Foo { Foo(int) {} operator bool() { return true; } };
and that
Foo some_calculation(int a, int b) { Foo result(a + b); /*...*/ return result; }
the example
if (some_calculation(3, 20) = 40) { /*...*/ }
compiles without a warning. Of course, this is rare. But isn't const correctness about making it hard for people to do things wrong? And with the expectation that people try things, that are wrong, the return type should be declared const.
And: g++ warns about ignoring the classifier, but does not ignore it. I think, the warning is about users that take the copy and ignore the const classifiers on their copy. But that should not be a warning, because this is absolutely correct behavior. And it makes sense to do this.
-pedantic 不应该只允许严格遵守 ISO 标准吗? 当然取决于 -std=...
Shouldn't -pedantic only allow strict adherence to the ISO standard? Depending on -std= of course...
此警告还有助于在声明返回指向不应修改的对象的指针的函数时避免混淆:
This warning is also useful to avoid confusion when declaring functions returning pointers to objects which should not be modified:
基本类型结果上的
const
与类类型结果上的const
之间存在差异,前者会被忽略,而后者通常会造成严重破坏。这就是编译器在第一种情况下发出警告的原因:这是一种特殊情况,可能不会做人们天真的所期望的事情。
对于现代编程来说,恕我直言,在类类型结果上添加关于 const 的警告会很好,因为它禁止移动语义; 对于人们所设想的哪怕一点点好处,都会付出相当惨重的代价。
There is a difference between
const
on a basic type result, where it's ignored, andconst
on a class type result, where it generally wreaks havoc.This is why the compiler warns in the first case: it's a special case, that may not do what one naïvely could expect.
For modern programming it would IMHO be nice also with a warning about
const
on class type result, since it prohibits move semantics; a rather severe cost for whatever little advantage one envisioned.Scott Meyers 指出这是有充分理由的为什么有人想要返回 const 值。 这是一个例子:
你看到我做错了什么了吗? 这段代码绝对正确,应该可以编译。 问题在于编译器无法理解您打算比较而不是分配值
40
。对于
const
返回值,上面的示例将无法编译。 好吧,至少如果编译器不丢弃 const 关键字的话。Scott Meyers pointed out that there's pretty good reason why someone would want to return
const
values. Here's an example:Do you see what I did wrong? This code is absolutely correct and should compile. The problem is that the compiler didn't understand that you intended tocompare instead of assign the value
40
.With a
const
return value the above example won't compile. Well, at least if the compiler doesn't discard theconst
keyword.