【问题标题】:Error c3892 iterator issue in VS2013VS2013 中的错误 c3892 迭代器问题
【发布时间】:2014-02-17 05:52:03
【问题描述】:

我正在将 Visual Studio 2008 VC++ 项目迁移到 Visual Studio 2013。在迁移我的一个项目时出现错误 C3892。这是一些重现问题的示例代码:

int _tmain(int argc, _TCHAR* argv[])
{
    struct student
    {
        int id;
        int marks;
        bool changed;

        bool operator < (const student& refParam) const
        {
            return false ;
        }
        student(int a,int b)
        {
            id=a;
            marks=b;
            changed=true;
        }
    };

    student x(10,500),y(15,600);
    std::multiset<student> myset;
    myset.insert(x);
    myset.insert(y);
    std::multiset<student>::reverse_iterator iter;
    for (iter=myset.rbegin(); iter != myset.rend(); ++iter)
    {
        std::cout<<iter->id<<"\n";
        std::cout<<iter->marks<<"\n";
        std::cout<<iter->changed<<"\n";
        iter->changed=false;
    }

    return 0;
}

尝试编译上面的会抛出错误:

error C3892: 'std::_Revranit<_RanIt,_Base>::operator ->' : you cannot assign to a variable that is const

但是,相同的代码在 Visual Studio 2008 中编译没有错误。我应该更改项目中的值吗?

【问题讨论】:

  • operator &lt; 不符合std::set 严格的弱订单要求。实现一个除了总是返回false 之外还做一些事情的方法。 set 的迭代器在 C++11 中更改为引用 const 元素而不是非常量元素,这会导致您的错误。
  • @WhozCraig return std::tie(id, mark, changed) &lt; std::tie(refParam.id, refParam.mark, refParam.changed) 不是最有效的方法,但我想这已经足够了。
  • @Joker_vD 如果我需要订购所有三个,我不会做任何其他方式。 std::tie 是猫的胡须。
  • @WhozCraig 好吧,我从来没有真正想知道a==b 是否应该等同于(!(a&lt;b)) &amp;&amp; (!(b&lt;a)),所以我总是为operator&lt; 写(任意)严格的总订单。
  • @Joker_vD 哈。有趣的。我其实更喜欢它。也许这是在我脑海中的事情,但严格的排序在我的灰质中总是很有效。

标签: c++ visual-c++ visual-studio-2012 stl


【解决方案1】:

C++ 11 中的所有多重集迭代器都指向一个 const 元素。如果要修改元素,则需要将其删除并插入一个新元素。 作为 hack,您可以将 struct 变量声明为可变(不推荐)。只有在您确定自己在做什么时才这样做

mutable bool changed;

你还应该写一个合适的操作符

【讨论】:

  • 不要使用mutable hack,而是将您的集合更改为地图并将“更改”放在可以安全变异的值部分。
【解决方案2】:

根据在 VS2010 以后实现的 C++11 标准,我们不能更改集合或多集合中的元素。默认情况下,迭代器引用一个常量元素。如果我们想改变一个集合或多重集合中的元素,我们必须进行显式类型转换。

上面代码中iter-&gt;changed=false抛出了C3892错误,但是如果我们把语句改成

const_cast<student&>(*item).changed=false;

相反,它将编译而没有任何错误。

【讨论】:

  • 更改集合成员很危险。 (特别是如果这会使它在集合中“乱序”。)
  • 虽然这会编译,但这是不对的。事实上,我很确定这是未定义的行为。请参阅ideone.com/RGKdqw 了解可能的后果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-18
  • 2011-02-13
  • 2011-02-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多