C++ 调用具有常量迭代器成员的类的析构函数时堆损坏

C++ 调用具有常量迭代器成员的类的析构函数时堆损坏,c++,heap-corruption,C++,Heap Corruption,我有一个类,它的成员是字符串和迭代器。 有一个GetNext()方法,它给我下一个元素并增加迭代器。使用来自外部的类,我检查是否有一个空字符串来指示deque的结束。 不幸的是,当调用构造函数并且使用GetNext获取最后一个元素时,我得到了堆损坏。 我想这是因为在deque中的最后一个字符串(空字符串)之后,迭代器仍然递增并指向内存中的某个地方? 然后析构函数试图释放内存然后崩溃 #include <iostream> #include <string> #inc

我有一个类,它的成员是字符串和迭代器。 有一个
GetNext()
方法,它给我下一个元素并增加迭代器。使用来自外部的类,我检查是否有一个空字符串来指示deque的结束。 不幸的是,当调用构造函数并且使用GetNext获取最后一个元素时,我得到了堆损坏。 我想这是因为在deque中的最后一个字符串(空字符串)之后,迭代器仍然递增并指向内存中的某个地方? 然后析构函数试图释放内存然后崩溃

   #include <iostream>
#include <string>
#include <deque>


class Foo 
{
public:
    Foo()
    {
        list.push_back("first elm");
        list.push_back("second elm");
        list.push_back(std::string());      
        pNextItem = list.begin();
    }

    virtual ~Foo(){}

    const std::string& GetNext() { return *pNextItem++; }

protected:

    std::deque<std::string> list;
    std::deque<std::string>::const_iterator pNextItem;
};


int main()
{
  {
  Foo foo;
  std::cout << foo.GetNext() << std::endl; //  "first elm"
  std::cout << foo.GetNext() << std::endl; //  "second elm"
  std::cout << foo.GetNext() << std::endl; //  ""
  //third call sets the iterator past the last element and causes a segfault
  std::cout << foo.GetNext() << std::endl;

  }

}
#包括
#包括
#包括
福班
{
公众:
Foo()
{
列表。向后推(“第一棵榆树”);
列表。推回(“第二榆树”);
list.push_back(std::string());
pNextItem=list.begin();
}
虚拟~Foo(){}
const std::string&GetNext(){return*pNextItem++;}
受保护的:
std::deque列表;
std::deque::const_迭代器pNextItem;
};
int main()
{
{
富富,;

std::cout在取消引用之前,您需要检查
pNextItem
是否等于
list.cend()
。这正是在第三次调用
foo.GetNext()
后发生的情况,此时您将取消引用最后一个元素并增加迭代器

deque::end

将迭代器返回到 容器

此元素用作占位符;尝试访问它会导致 未定义的行为


我对示例进行了编辑,以包含用法和指向tutorialspoint.com上可编译代码的链接(猜得很好;)谢谢您的回答。这是一个好方法吗?:
const std::string&GetNext(){if(pNextItem==list.end())return*pNextItem;return*pNextItem++;}
no,您仍将尝试取消引用
list.cend()
这是UB。因此,要么返回一个特殊值(如空字符串),要么使用返回代码/异常/可选来标识您到达了容器的末尾。当然,谢谢…现在检查空字符串元素
const std::string&GetNext(){if(pNextItem->empty())return*pNextItem;return*pNextItem++}