从动态数组中删除元素而不更改索引顺序

时间:2011-09-05 18:59:37

标签: c++ arrays indexing

我一直试图在不改变索引顺序的情况下擦除数组中的元素,例如:

class MyObject  
{  
    int id;  
public:  
    MyObject() { }  
    void setId( int i ) { id = i; }  
    void showId() { std::cout << "ID: "<< id << "\n"; }
};  
MyObject *myArray;

int main ( )  
{  
    myArray = new myArray[6];  
    for( int i = 0; i < 6; i++ )  
    {  
        myArray[i]->setId(i); 
        myArray[i]->showId();
    }  
}  

我想删除myArray[3]而不更改其他人的索引。 e.g:

myArray[0] = ID: 1  
myArray[1] = ID: 2  
myArray[2] = nothing  
myArray[3] = ID: 4  
myArray[4] = ID: 5  
myArray[5] = ID: 6    

我尝试使用use memset(),但它没有用。

memset(&myArray[3],0,sizeof(MyObject));

4 个答案:

答案 0 :(得分:1)

C ++语言中没有“无”的东西。一旦有了数组,该数组的所有元素都将包含“something”。只有将所有其他元素保留在原始位置,才能使消失的数组元素无法生成。你不能在数组中创建一个洞。

在这种情况下你所能做的就是将一些元素标记为“已删除”,然后再将其识别为。当然,该元素将继续在物理上存在。是您必须将其识别为“已删除”并在进一步处理中忽略它。您可以向对象添加一些bool is_deleted字段,也可以使用id的某些保留值(如-1)来表示已删除的元素。

在使用memset的示例中,您基本上将id设置为零。 0id有效值吗?如果不是,则0是标记已删除元素的不错选择。从这个意义上讲,你的memset尝试完全没问题。虽然我建议明确指定零id,而不使用memset

答案 1 :(得分:0)

您正在调用memset在对象实例的顶部写一堆零。不要这样做!如果你的班级是真正的POD课程,你可以逃脱它。你可能最终只是将ID设置为0.但也许你的班级还有更多你没有展示的。无论如何,即使它不是POD,也不要像那样使用memset

您可以存储指向对象的指针,并使用空指针指示那里没有任何内容。我会用std::vector<MyObject*>执行此操作。或者您使用Sentinel对象实例,例如ID为-1。

另一件可能是问题的事情是您似乎使用了基于1的索引。 C ++数组从0开始,因此第一个元素是myArray[0]而不是myArray[1]

答案 2 :(得分:0)

使用memset就是将该对象的所有字节设置为0.这通常等同于将id设置为0,因为对象的内存是其成员的内存(不是计数vtables,填充等)。但是不要那样做。

执行此操作的一种方法是使用new并使用指针数组。

MyObject* myArray[6];

int main ( )  
{ 
    for( int i = 0; i < 6; i++ )  
    {
        myArray[i] = new MyObject;
        myArray[i]->setId(i); 
        myArray[i]->showId();
    }  
}

然后全部显示:

for (int i = 0; i < 6; i++) {
    cout << "myArray[" << i << "] = ";
    if (myArray[i])
        myArray[i]->showId();
    else
        cout << "nothing" << endl;
}

然后当你想删除一个对象时,delete并将其指针设置为NULL

delete myArray
myArray[3] = NULL;

然后当您对myArray中的某个对象执行任何操作时,必须检查它是否为NULL以查看它是否为有效对象。

答案 3 :(得分:0)

考虑boost::optional

typedef boost::optional<MyObject> MyObjectOpt;
MyObjectOptArr *myArray;

语法/用法略有不同(类似于使用指针):

for (int i = 0; i < 6; ++i) {      
    if (myArray[i])
        cout << "myArray[" << i << "] = " << *(myArray[N]);
    else
        cout << "nothing" << endl;
}

要取消设定值,请执行以下操作:

myArray[N] = boost::none;