我一直在把一大块 Java 代码移植到 C++, 并且不得不执行类似 LinkedHashSet 的东西。 我用 Bust s 多 Index 容器制作了链接HashSet/ Map 的合理传真 。
当我在输入代码时,我正用多指数进入一些有趣的东西,因为包含的物体是不可变的(除非您将该类的特定字段标记为可变的 ) 。 但是,如果密钥是从包含的类别中某些可变成员计算出来的,那么事情就会变得有趣。
为了澄清一些我认为我在爪哇写了一个微不足道的例子来检查他们的链接HashSet的行为。结果对我来说有点令人吃惊;它们似乎表现得像BOSTS多指数容器,因为如果一个包含的物体被修改(你可能会期待如此),指数就不会再生;然而,编译者并没有以任何方式抱怨 -- -- 似乎很容易射穿自己的脚(我所输入的代码似乎犯下了所提到的罪恶,谁知道它是如何运作的)。
这仅仅是对爪哇缺乏康斯特-辩论者的限制吗? 还是我做了一件特别愚蠢或棘手的事?
以下是一个微不足道的例子:
class StringContainer
{
public String s;
public StringContainer(String s)
{
this.s = s;
}
public boolean equals(Object t1)
{
StringContainer other = (StringContainer) t1;
return this.s == other.s;
}
public int hashCode()
{
int val = 8;
for (int i = 0; i < s.length(); i++)
val += s.charAt(i);
return val;
}
public String toString()
{
return s;
}
}
class test
{
public static void main(String[] args)
{
Set<StringContainer> set = new LinkedHashSet();
set.add(new StringContainer("Foo"));
set.add(new StringContainer("Bar"));
set.add(new StringContainer("Baz"));
set.add(new StringContainer("Qux"));
Iterator<StringContainer> it = set.iterator();
while (it.hasNext())
{
StringContainer s = it.next();
if (s.s == "Baz")
s.s = "Baz2";
System.out.println(s);
}
System.out.println("
Re-iterate:
");
it = set.iterator();
while (it.hasNext())
{
StringContainer s = it.next();
System.out.println(s);
}
System.out.println();
if (set.contains(new StringContainer("Foo")))
System.out.println("Contains Foo");
if (set.contains(new StringContainer("Baz")))
System.out.println("Contains Baz");
else
System.out.println("Does not contain Baz");
if (set.contains(new StringContainer("Baz2")))
System.out.println("Contains Baz2");
else
System.out.println("Does not contain Baz2");
}
}
它印刷了以下材料:
Foo
Bar
Baz2
Qux
Re-iterate:
Foo
Bar
Baz2
Qux
Contains Foo
Does not contain Baz
Does not contain Baz2
有趣的是,它知道巴兹已经改变;然而它仍然没有找到巴兹2号。
显然,这是个构思,但我所看到的非常可信的代码似乎(通过多重间接法)导致了这个问题。 至少用“促进多指数 ” ( move multic index ), 您必须把一个循环器编织成一个循环器才能造成这个问题!