可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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?
回答1:
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.
回答2:
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:
-Wno-ignored-qualifiers
Hope this helps.
回答3:
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
int& getNonconstReference() {
return _myInt;
}
Which will should be:
void setMyInt(int n) {
_myInt = n;
}
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.
回答4:
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.
回答5:
Shouldn't -pedantic only allow strict adherence to the ISO standard? Depending on -std= of course...
回答6:
This warning is also useful to avoid confusion when declaring functions returning pointers to objects which should not be modified:
// "warning: type qualifiers ignored on function return type"
// as the pointer is copied.
Foo* const bar();
// correct:
const Foo* bar();
回答7:
There is a difference between const
on a basic type result, where it's ignored, and const
on a class type result, where it generally wreaks havoc.
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.
}
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.
回答8:
Scott Meyers pointed out that there's pretty good reason why someone would want to return const
values. Here's an example:
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)
{
}
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 the const
keyword.