Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 矢量擦除函数删除错误对象_C++_Vector_Stdvector - Fatal编程技术网

C++ 矢量擦除函数删除错误对象

C++ 矢量擦除函数删除错误对象,c++,vector,stdvector,C++,Vector,Stdvector,我有一个向量声明为: vector<Curve> workingSet; 矢量工作集; Curve是我创建的一个类,它包含一个字符串“name”和一个由构造函数动态分配的结构数组 我有一个循环,应该从向量中删除2项(共4项) vector<Curve>::iterator it = workingSet.begin(); //remove tbi's children from the working set for ( ; it != work

我有一个向量声明为:

vector<Curve> workingSet;
矢量工作集;
Curve是我创建的一个类,它包含一个字符串“name”和一个由构造函数动态分配的结构数组

我有一个循环,应该从向量中删除2项(共4项)

vector<Curve>::iterator it = workingSet.begin();

    //remove tbi's children from the working set
    for (  ;  it != workingSet.end();){
        if (it->thisName == tbi.childAName ||it->thisName == tbi.childBName)
            it= workingSet.erase(it);
        else
            ++it;
        }
vector::iterator it=workingSet.begin();
//从工作集中删除tbi的子项
for(;it!=workingSet.end();){
如果(it->thisName==tbi.childAName | | it->thisName==tbi.childBName)
它=工作集。擦除(它);
其他的
++它;
}
当调试器到达.erase(it)调用时,我可以看到“it”迭代器指向向量中的曲线2。这是好的;我希望从向量中删除曲线2

vector<Curve>::iterator it = workingSet.begin();

    //remove tbi's children from the working set
    for (  ;  it != workingSet.end();){
        if (it->thisName == tbi.childAName ||it->thisName == tbi.childBName)
            it= workingSet.erase(it);
        else
            ++it;
        }
然后,调试器将我带到析构函数(我在那里有一个断点),它大概应该是销毁曲线2。但是当我看这只手表时,我可以看到被破坏的曲线是曲线4!析构函数然后根据需要对对象中的数组执行“delete[]”操作,并将数组指针设置为NULL

当调试器返回程序,完成erase()调用后,我可以看到向量2已从数组中删除,曲线4仍然存在。曲线4的数组指针仍然指向与以前相同的位置,但内存已被释放,数组包含垃圾

有人能提出为什么曲线4被弄乱了吗

注意:(1)curve类有一个复制构造函数,它执行“深度”复制。 注:(2)这门课/课程的内容比我在这里提到的还要多

顺便说一句,根据调试器,曲线2和曲线4中的数组指针指向不同的位置并包含不同的值


编辑:我现在已经实现了复制分配。现在,正确的项似乎正在从向量中删除,但仍在调用错误的析构函数!但是,当调试器返回到数组时,曲线4仍然完好无损。

当从向量中删除一个项时,它后面的所有元素都向前移动以填充空白。如果您的编译器还不支持
move
,那么可以通过复制所有元素来完成,并且向量中的最后一项(现在复制到它之前的项)是重复项,将被删除


至少它应该是这样工作的。

在我看来,vector::erase不能用于本地构造的非平凡数据类型的向量(不是在堆上构造的对象,我现在不知道正确的名称)。我有与您描述的完全相同的行为,最后一个元素被销毁两次(如果您的对象具有由析构函数释放的内存,则特别危险),并且您删除的元素永远不会被销毁。我不知道为什么会发生这种情况,但这是一个值得警惕的陷阱

以下是解决此问题的一种方法:

#include <iostream>
#include <vector>
#include <memory>

using namespace std;

class MyClass 
{
   public:
    int *x;
    MyClass(int x)
    {
       cout << "MyClass Constructor " << x << endl;
       this->x = new int(x);
    }
    MyClass(const MyClass& obj)
    {
       this->x = new int(*obj.x);
       cout << "copy constructor " << *this->x << endl;
    }
    ~MyClass()
    {
       cout << "MyClass Destructor " << *x << endl;
       delete x;
    }
};
int main(int argc, char* argv[])
{
   // incorrect
   vector<MyClass> bad_vect;
   for(int i=0;i<3;i++){
      bad_vect.push_back(MyClass(i));
      // causes a bunch of copying to happen.
      // std::move does not seem to fix this either
      // but in the end everything gets constructed as we'd like
   }
   cout << " ---- " << endl;
   bad_vect.erase(bad_vect.begin() + 1); // we expect this to remove item with x = 1 and destruct it.
   // but it does NOT do that, it does remove the item with x=1 from the vector
   // but it destructs the last item in the vector, with x=2, clearly
   // not what we want. The destructor for object with x=1 never gets called
   // and the destructor for the last item gets called twice.
   // The first time with x=2 and since that memory is freed, the 2nd time
   // it prints garbage. Strangely the double-free doesn't crash the prog
   // but I wouldn't count on that all the time.
   // Seems some parts of STL have pitfalls with locally constructed objects
   cout << " ------------ " << endl;
   // below fixes this
   vector<unique_ptr<MyClass> >vect;
   for(int i=0;i<3;i++){
      unique_ptr<MyClass> ptr(new MyClass(i));
      vect.push_back( move( ptr )); // move is required since unique_ptr can only have one owner
      // or the single one-liner below
      //vect.push_back( move( unique_ptr<MyClass>(new MyClass(i)) ));
   }
   // the above prints out MyClass Constructor 0,1,2, etc
   vect.erase(vect.begin() + 1); // remove the 2nd element, ie with x=1
   // the above prints out MyClass Destructor 1, which is what we want

   for(auto& v : vect){
     cout << *(v->x) << endl;
   } // prints out 0 and 2
   return 0; // since we're using smart pointers, the destructors for the
           // remaining 2 objects are called. You could use regular pointers
           // but you would have to manually delete everything. shared_ptr
           // also works and you don't need the move(), but with a bit more overhead
}
#包括
#包括
#包括
使用名称空间std;
类MyClass
{
公众:
int*x;
MyClass(int x)
{

你能不能提供一个可编译的最小示例来说明这个问题?你的口头描述没有多大帮助。无论如何:看看擦除/删除习惯用法。我们有很多问题都是这样回答的。另外一件事:你只提到了一个复制ctor,你也实现了复制分配吗?我还没有实现复制分配我现在就这么做,然后再回复你。展示你描述的行为的最小可编译示例。我观察到同样的问题。你使用了哪种编译器?