当我第一次使用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吗?
答案 0 :(得分:91)
它没有违反标准。这就是为什么他们警告而不是错误。
确实你是对的 - 领先的const
是多余的。编译器警告你,因为你添加的代码在其他情况下可能意味着什么,但在这种情况下没有任何意义,并且它希望确保在你的返回值结果可以修改之后你不会失望。
答案 1 :(得分:18)
在编译使用Boost.ProgramOptions的代码时遇到此警告。我使用-Werror
所以警告是在杀死我的构建,但由于警告的来源是在Boost的深处,我无法通过修改我的代码来摆脱它。
经过多次挖掘后,我找到了禁用警告的编译器选项:
-Wno-ignored-qualifiers
希望这有帮助。
答案 2 :(得分:4)
返回一个常量值只有在返回引用或指针时才有意义(在这种情况下指针指向常量而不是常量指针),因为调用者能够修改引用的(指向的)值。
对与您的问题无关的代码的另一个评论: 我认为最好使用setter而不是
int& getNonconstReference() {
return _myInt;
}
应该是:
void setMyInt(int n) {
_myInt = n;
}
此外,将const引用返回给int是没用的。对于复制或移动更昂贵的更大对象来说,它确实有意义。
答案 3 :(得分: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。 并且:g ++警告忽略分类器,但不要忽略它。我认为,警告是关于获取副本并忽略副本上的const分类器的用户。但这不应该是一个警告,因为这是绝对正确的行为。这样做是有意义的。
答案 4 :(得分:1)
不应该只允许严格遵守ISO标准吗?取决于-std =当然......
答案 5 :(得分:1)
当声明返回指向不应修改的对象的指针的函数时,此警告也有助于避免混淆:
// "warning: type qualifiers ignored on function return type"
// as the pointer is copied.
Foo* const bar();
// correct:
const Foo* bar();
答案 6 :(得分: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
警告也很好,因为它禁止移动语义;无论人们设想什么样的优势,都要付出相当沉重的代价。
答案 7 :(得分:-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
关键字。