VC10 unordered_set / map移动构造函数bug?

时间:2012-10-08 18:15:27

标签: visual-studio-2010 unordered-map unordered-set move-constructor

似乎VC10(Visual Studio 2010)下的unordered_set / map的移动构造函数在被调用后将右侧置于未定义状态,导致其他操作(例如“insert”)失败。移动赋值运算符似乎工作正常。但是,在所有情况下,正常的集合/映射似乎都表现正常。此外,在VC11(Visual Studio 2012)下,一切似乎都运行正常。

这是VC10下_Hash实现的错误还是我遗漏了什么?提前感谢任何投入!

#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>

std::set<int> si0;
std::unordered_set<int> usi0;

std::map<int, int> mii0;
std::unordered_map<int, int> umii0;

int _tmain(int argc, _TCHAR* argv[])
{
    si0.insert(0);
    si0.insert(1);
    si0.insert(2);
    std::set<int> si( std::move(si0) ); // fine!
    si0.insert(666);

    usi0.insert(0);
    usi0.insert(1);
    usi0.insert(2);
    //std::unordered_set<int> usi( std::move(usi0) ); // this seems to put usi0 to an undefined state, which makes 'insert' below cry!
    std::unordered_set<int> usi; usi = std::move(usi0); // this works!
    usi0.insert(666);

    mii0[0] = 0;
    mii0[1] = 1;
    mii0[2] = 2;
    std::map<int, int> mii( std::move(mii0) ); // fine!
    mii0[666] = 666;

    umii0[0] = 0;
    umii0[1] = 1;
    umii0[2] = 2;
    //std::unordered_map<int, int> umii( std::move(umii0) ); // this seems to put umii0 to an undefined state, which makes 'insert' below cry!
    std::unordered_map<int, int> umii; umii = std::move(umii0); // this works!
    umii0[666] = 666;

    return 0;
}

1 个答案:

答案 0 :(得分:1)

Alrighty,在深入挖掘VC10下的_Hash类实现,并将其与VC11的实现进行比较之后,我注意到VC10下的_Hash类的移动构造函数从未初始化其'_Max_bucket_size'成员,然后逻辑交换这个未初始化的右侧的值(移动的_Hash实例),使右侧处于未初始化状态。

如果移动构造函数的右侧实际上是临时对象,这很好,但我的逻辑依赖于移动构造函数来“重置”右侧对象,此后将重建右侧对象。

移动赋值版本的工作原理是它要求左手侧对象以某种方式正确构造(在这种情况下,默认构造,正确初始化'_Max_bucket_size'),并且当将其交换到右侧时,右手一方不会处于不良状态。然而,让左侧从左侧接受交换状态的右侧不符合移动赋值运算符的标准行为,它应该重置右侧,这样做比纯交换更多的东西!

VC11中的相应实现似乎已经纠正了行为并符合标准。