错误:将 xxx 作为 xxx 的“this”参数传递会丢弃限定符
Posted
技术标签:
【中文标题】错误:将 xxx 作为 xxx 的“this”参数传递会丢弃限定符【英文标题】:error: passing xxx as 'this' argument of xxx discards qualifiers 【发布时间】:2011-08-23 19:48:06 【问题描述】:#include <iostream>
#include <set>
using namespace std;
class StudentT
public:
int id;
string name;
public:
StudentT(int _id, string _name) : id(_id), name(_name)
int getId()
return id;
string getName()
return name;
;
inline bool operator< (StudentT s1, StudentT s2)
return s1.getId() < s2.getId();
int main()
set<StudentT> st;
StudentT s1(0, "Tom");
StudentT s2(1, "Tim");
st.insert(s1);
st.insert(s2);
set<StudentT> :: iterator itr;
for (itr = st.begin(); itr != st.end(); itr++)
cout << itr->getId() << " " << itr->getName() << endl;
return 0;
排队:
cout << itr->getId() << " " << itr->getName() << endl;
它给出一个错误:
../main.cpp:35: 错误:将 'const StudentT' 作为 'int StudentT::getId()' 的 'this' 参数传递会丢弃限定符
../main.cpp:35: 错误:将 'const StudentT' 作为 'std::string StudentT::getName()' 的 'this' 参数传递会丢弃限定符
这段代码有什么问题?谢谢!
【问题讨论】:
代码 sn-p 中的第 35 行在哪里? 我希望 GCC 能改进这个错误信息,例如“丢弃限定符”->“破坏 const 正确性” @jfritz42:对于它丢弃volatile
的情况会令人困惑
@PlasmaHH 错误消息将分为“破坏 const 正确性”和“破坏 volatile 正确性”。现在,没有多少人会考虑 volatile 正确
【参考方案1】:
std::set
中的对象存储为const StudentT
。因此,当您尝试使用 const
对象调用 getId()
时,编译器会检测到问题,主要是您在 const 对象上调用非常量成员函数,这是不允许的,因为非常量成员函数不承诺不会修改对象;所以编译器会做出一个安全的假设,即getId()
可能会尝试修改该对象,但同时它也注意到该对象是常量;所以任何修改 const 对象的尝试都应该是一个错误。因此编译器会生成一条错误消息。
解决方案很简单:将函数设为:
int getId() const
return id;
string getName() const
return name;
这是必要的,因为现在您可以在 const 对象上调用 getId()
和 getName()
:
void f(const StudentT & s)
cout << s.getId(); //now okay, but error with your versions
cout << s.getName(); //now okay, but error with your versions
作为旁注,您应该将operator<
实现为:
inline bool operator< (const StudentT & s1, const StudentT & s2)
return s1.getId() < s2.getId();
注意参数现在是const
参考。
【讨论】:
这么清晰的解释。谢谢。但我想知道你的最后一个代码 sn-p。为什么在函数参数中使用引用?const StudentT & s1, const StudentT & s2
?
@RafaelAdel:您使用引用来避免不必要的复制,const
因为函数不需要修改对象,所以const
在编译时强制执行此操作。【参考方案2】:
不修改类实例的成员函数应声明为const
:
int getId() const
return id;
string getName() const
return name;
每当您看到“丢弃限定符”时,它指的是const
或volatile
。
【讨论】:
@Fred - 你认为绝对需要向不修改类实例的成员函数添加 const 修饰符吗?在这种情况下,错误还有其他原因吗?我对此表示怀疑,因为在我编写的大多数 getter 中,我都没有添加 const 修饰符。 @Mahesh:是的,它是const correctness 的一部分。我不确定const
是从哪里来的,但我怀疑set
正在从迭代器返回一个常量引用,以防止实例更改从而使集合无效。
@Mahesh:不会通过我的代码审查。我有一位同事称我为“能干的人”。 8v) 将foo obj;
更改为const foo obj;
一次,看看会发生什么。或者将const
引用传递给foo
。
@Mahesh:就像我说的那样——如果set
中的元素发生更改,则顺序可能会被打乱,然后集合不再有效。在map
中,只有键是const
。在set
中,整个对象才是真正的关键。
@Mahesh: const 是必要的,否则你不能用 const 对象调用它们。在我的回答中查看函数f()
。【参考方案3】:
实际上,C++ 标准(即C++ 0x draft)说(@Xeo 和@Ben Voigt 向我指出这一点):
23.2.4 关联容器5 用于设置和多重设置值类型 与密钥类型相同。对于地图 和multimap它等于pair。关联中的键 容器是不可变的。6 的迭代器 关联容器是 双向迭代器类别。为了 关联容器的值 类型与键类型相同,两者 iterator 和 const_iterator 是 常量迭代器。未指定 是否迭代器和 const_iterator 是同一类型。
所以 VC++ 2008 Dinkumware 实现是错误的。
旧答案:
您收到该错误是因为在 std lib 的某些实现中,set::iterator
与 set::const_iterator
相同。
例如 libstdc++(与 g++ 一起提供)有它(完整源代码请参见here):
typedef typename _Rep_type::const_iterator iterator;
typedef typename _Rep_type::const_iterator const_iterator;
在 SGI 的 docs 中它声明:
iterator Container Iterator used to iterate through a set.
const_iterator Container Const iterator used to iterate through a set. (Iterator and const_iterator are the same type.)
另一方面,VC++ 2008 Express 编译您的代码,而不会抱怨您在 set::iterator
s 上调用非 const 方法。
【讨论】:
【参考方案4】:让我举一个更详细的例子。至于下面的结构:
struct Count
uint32_t c;
Count(uint32_t i=0):c(i)
uint32_t getCount()
return c;
uint32_t add(const Count& count)
uint32_t total = c + count.getCount();
return total;
;
正如您在上面看到的,IDE(CLion) 将给出提示Non-const function 'getCount' is called on the const object
。在add
方法中count
被声明为const对象,但getCount
方法不是const方法,所以count.getCount()
可能会改变count
中的成员。
编译错误如下(我的编译器中的核心消息):
error: passing 'const xy_stl::Count' as 'this' argument discards qualifiers [-fpermissive]
要解决上述问题,您可以:
-
将方法
uint32_t getCount()...
更改为uint32_t getCount() const ...
。所以count.getCount()
不会更改count
中的成员。
或
-
将
uint32_t add(const Count& count)...
更改为uint32_t add(Count& count)...
。所以count
不关心更换成员。
关于你的问题,std::set中的对象存储为const StudentT,但是方法getId
和getName
不是const,所以你给出了上面的错误。
您也可以查看此问题Meaning of 'const' last in a function declaration of a class? 了解更多详情。
【讨论】:
以上是关于错误:将 xxx 作为 xxx 的“this”参数传递会丢弃限定符的主要内容,如果未能解决你的问题,请参考以下文章
TypeError: this.xxx.substring is not a function的解决办法
1130 - Host'xxx.xxx.xxx.xxx' is not allowed to connect to this MySQL server解决Navicat连接MySQL报
React useState 挂钩错误:“xxx”类型的参数不可分配给“SetStateAction<xx>”类型的参数
Ubuntu报“xxx is not in the sudoers file.This incident will be reported” 错误解决方法
Ubuntu报“xxx is not in the sudoers file.This incident will be reported” 错误解决方法