class Test
{
private:
int v;
public:
Test(int h)
{
v = h;
}
int getV()
{
return v;
}
bool operator < (const Test& b) const
{
return v < b.v;
}
};
int main()
{
set <Test> st;
for(int i = 1; i <= 10; i++)
{
Test t(i);
st.insert(t);
}
for(set<Test>::iterator it = st.begin(); it != st.end(); it++)
{
cout << (*it).getV() << endl;
//Test it2 = *it;
//cout << it2.getV() << endl;
}
return 0;
}
将是
|错误:将'const Test'作为'int Test :: getV()'的'this'参数传递,丢弃限定符[-fpermissive] |
但如果我使用Test it2 = *it; cout << it2.getV() << endl;
,它会很好用。为什么它使用'const Test'这个词以及为什么代码不能工作?
答案 0 :(得分:6)
std::set
迭代器返回const引用,因为set
已排序,如果更改集合中对象的值,则它可能位于新值的错误位置。这可能会使对象无法找到并且更糟糕。
当你这样做时
Test it2 = *it;
您正在复制该对象,您可以根据需要修改该副本。你不能通过修改副本来搞乱set
。
问题是您的getV()
方法没有正确的const限定。它应该是:
int getV() const
{
return v;
}
然后第一个代码将编译并正常工作。
如果没有将const应用于正确的地方,通常会导致这类问题。你应该努力正确地应用const限定。
答案 1 :(得分:1)
set
迭代器是一个const迭代器。您需要将getV()
标记为常量(因为它不会更改对象,所以它应该是无论如何):
int getV() const // <--
{
return v;
}
答案 2 :(得分:-3)
另一种方法是删除迭代器引用的对象的常量。在这种情况下,getV不需要是const方法。检查以下修改后的代码:
for(set<Test>::iterator it = st.begin(); it != st.end(); it++)
{
cout << (const_cast<Test*>(&(*it)))->getV() << endl;
//Test it2 = *it;
//cout << it2.getV() << endl;
}
我不明白为什么上面的答案被低估了。我只是举了另一个例子。在某些情况下,我们必须这样做。有时我们需要在对象中设置一些值。下注选民能否看到下面这个例子的原因:
#include <iostream>
#include <set>
using namespace std;
class Test
{
private:
int v;
int w;
public:
Test(int h, int i)
{
v = h;
w = i;
}
int getV() const
{
return v;
}
int getW() const
{
return w;
}
void setW(int a) // This will not screw up the set as only v is used for comparison
{
w = a;
}
// Operator < is not using only v for comparison
// of objects and not using w for that purpose
bool operator < (const Test& b) const
{
return v < b.v;
}
};
int main()
{
set <Test> st;
for(int i = 10; i >= 0; i--)
{
Test t(i, i);
st.insert(t);
}
for(set<Test>::iterator it = st.begin(); it != st.end(); it++)
{
const_cast<Test*>(&(*it))->setW(1000);
}
for(set<Test>::iterator it = st.begin(); it != st.end(); it++)
{
cout << it->getV() << " " << it->getW() << endl;
}
return 0;
}