【问题标题】:VC10 unordered_set/map move constructor bug?VC10 unordered_set/map 移动构造函数错误?
【发布时间】:2012-10-08 18:15:26
【问题描述】:

似乎 VC10 (Visual Studio 2010) 下 unordered_set/map 的移动构造函数在被调用后将右侧置于未定义状态,导致其他操作(如“插入”)惨遭失败。移动赋值运算符似乎工作正常。不过,正常的集合/映射似乎在所有情况下都表现正确。此外,在 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;
}

【问题讨论】:

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


    【解决方案1】:

    好吧,在深入研究了VC10下的_Hash类实现,并与VC11的比较后,我注意到VC10下的_Hash类的移动构造函数从未初始化它的'_Max_bucket_size'成员,然后逻辑交换这个未初始化的右侧的值(移动的 _Hash 实例),使右侧处于未初始化状态。

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

    移动分配版本的工作原理是,它需要以某种方式正确构造左侧对象(在这种情况下,默认构造,正确初始化 '_Max_bucket_size'),并且在将其交换到右侧时,右手侧不处于不良状态。然而,让右侧从左侧获取交换状态不符合移动赋值运算符的标准行为,它应该 reset 右侧,这不仅仅是纯粹的交换!

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-22
      • 2018-02-27
      • 1970-01-01
      • 2018-08-21
      • 1970-01-01
      • 2019-12-09
      • 2017-11-03
      相关资源
      最近更新 更多