我一直试图在不改变索引顺序的情况下擦除数组中的元素,例如:
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));
答案 0 :(得分:1)
C ++语言中没有“无”的东西。一旦有了数组,该数组的所有元素都将包含“something”。只有将所有其他元素保留在原始位置,才能使消失的数组元素无法生成。你不能在数组中创建一个洞。
在这种情况下你所能做的就是将一些元素标记为“已删除”,然后再将其识别为。当然,该元素将继续在物理上存在。是您必须将其识别为“已删除”并在进一步处理中忽略它。您可以向对象添加一些bool is_deleted
字段,也可以使用id
的某些保留值(如-1
)来表示已删除的元素。
在使用memset
的示例中,您基本上将id
设置为零。 0
是id
有效值吗?如果不是,则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)
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;